编写高质量代码改善C#程序的157个建议——建议49:在Dispose模式中应提取一个受保护的虚方法
建议49:在Dispose模式中应提取一个受保护的虚方法
在标准的Dispose模式中,真正的IDisposable接口的Dispose方法并没有做实际的清理工作,它其实是调用了下面的这个带bool参数且受保护的的虚方法:
/// <summary>
/// 非密封类修饰用protected virtual
/// 密封类修饰用private
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
//省略代码
}
之所以提供这样一个受保护的虚方法,是因为考虑了这个类型会被其他类型继承的情况。如果类型存在一个子类,子类也许会实现自己的Dispose模式。受保护的虚方法用来提醒子类:必须在自己的清理方法时注意到父类的清理工作,即子类需要在自己的释放方法中调用base.Dispose方法。
public class DerivedSampleClass : SampleClass
{
//子类的非托管资源
private IntPtr derivedNativeResource = Marshal.AllocHGlobal();
//子类的托管资源
private AnotherResource derivedManagedResource = new AnotherResource();
//定义自己的是否释放的标识变量
private bool derivedDisposed = false; /// <summary>
///重写父类Dispose方法
/// </summary>
/// <param name="disposing"></param>
protected override void Dispose(bool disposing)
{
if (derivedDisposed)
{
return;
}
if (disposing)
{
// 清理托管资源
if (derivedManagedResource != null)
{
derivedManagedResource.Dispose();
derivedManagedResource = null;
}
}
// 清理非托管资源
if (derivedNativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(derivedNativeResource);
derivedNativeResource = IntPtr.Zero;
}
//调用父类的清理代码
base.Dispose(disposing);
//让类型知道自己已经被释放
derivedDisposed = true;
}
} public class SampleClass : IDisposable
{
//演示创建一个非托管资源
private IntPtr nativeResource = Marshal.AllocHGlobal();
//演示创建一个托管资源
private AnotherResource managedResource = new AnotherResource();
private bool disposed = false; /// <summary>
/// 实现IDisposable中的Dispose方法
/// </summary>
public void Dispose()
{
//必须为true
Dispose(true);
//通知垃圾回收机制不再调用终结器(析构器)
GC.SuppressFinalize(this);
} /// <summary>
/// 不是必要的,提供一个Close方法仅仅是为了更符合其他语言(如
/// C++)的规范
/// </summary>
public void Close()
{
Dispose();
} /// <summary>
/// 必须,防止程序员忘记了显式调用Dispose方法
/// </summary>
~SampleClass()
{
//必须为false
Dispose(false);
} /// <summary>
/// 非密封类修饰用protected virtual
/// 密封类修饰用private
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
if (disposed)
{
return;
}
if (disposing)
{
// 清理托管资源
if (managedResource != null)
{
managedResource.Dispose();
managedResource = null;
}
}
// 清理非托管资源
if (nativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
//让类型知道自己已经被释放
disposed = true;
} public void SamplePublicMethod()
{
if (disposed)
{
throw new ObjectDisposedException("SampleClass", "SampleClass is disposed");
}
//省略
}
} class AnotherResource : IDisposable
{
public void Dispose()
{
}
}
如果不为类提供这个受保护的虚方法,很有可能让开发者设计子类的时候忽略掉父类的清理工作。所以要在类型的Dispose模式中提供一个受保护的虚方法。
转自:《编写高质量代码改善C#程序的157个建议》陆敏技
编写高质量代码改善C#程序的157个建议——建议49:在Dispose模式中应提取一个受保护的虚方法的更多相关文章
- 编写高质量代码改善C#程序的157个建议
1.使用StringBuilder或者使用string.Format("{0}{1}{2}{3}", a, b, c, d)拼接字符串. 2.使用默认转型方法,比如使用类型内置的P ...
- 编写高质量代码改善C#程序的157个建议[1-3]
原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...
- 读书--编写高质量代码 改善C#程序的157个建议
最近读了陆敏技写的一本书<<编写高质量代码 改善C#程序的157个建议>>书写的很好.我还看了他的博客http://www.cnblogs.com/luminji . 前面部 ...
- 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试
建议157:从写第一个界面开始,就进行自动化测试 如果说单元测试是白盒测试,那么自动化测试就是黑盒测试.黑盒测试要求捕捉界面上的控件句柄,并对其进行编码,以达到模拟人工操作的目的.具体的自动化测试请学 ...
- 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本
建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...
- 编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码
建议155:随生产代码一起提交单元测试代码 首先提出一个问题:我们害怕修改代码吗?是否曾经无数次面对乱糟糟的代码,下决心进行重构,然后在一个月后的某个周一,却收到来自测试版的报告:新的版本,没有之前的 ...
- 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣
建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...
- 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释
建议153:若抛出异常,则必须要注释 有一种必须加注释的场景,即使异常.如果API抛出异常,则必须给出注释.调用者必须通过注释才能知道如何处理那些专有的异常.通常,即便良好的命名也不可能告诉我们方法会 ...
- 编写高质量代码改善C#程序的157个建议——建议152:最少,甚至是不要注释
建议152:最少,甚至是不要注释 以往,我们在代码中不写上几行注释,就会被认为是钟不负责任的态度.现在,这种观点正在改变.试想,如果我们所有的命名全部采用有意义的单词或词组,注释还有多少存在的价值. ...
随机推荐
- bzoj 3998 [TJOI2015]弦论——后缀自动机
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3998 相同子串算多个的话,先求好 right ,然后求一个 sm 表示走到这个点之后有几种走 ...
- dubbox消费者启动成功,却无法连接注册中心
使用dubbox作为服务提供端很好实现,因为git的说明和网上有很多的例子可供参考,但是消费端都一笔带过,简单得很,初学者往往以为只要配置如下3样东西就够了: <?xml version=&qu ...
- Eclipse里git提交冲突rejected – non-fast-forward
Eclipse里commit代码,其实只是提交到本地仓库,需要push才会提交到远程的git仓库,这时是一个本地仓库到远程仓库的同步过程.Git是分布式的,每个人在本地仓库维护本地的自己的那一份代码, ...
- 在laravel中使用支付宝手机网站支付 和 支付宝退款
1.在蚂蚁金服开放平台中申请对应的应用,并根据提示进行签约 2.给对应的应用信息 生成私钥和公钥(私钥会保存在本地,公钥会放在对应的应用信息中) 3.下载手机网站支付 对应的php sdk 4.将sd ...
- [教程]centos卸载、安装mysql(源码编译安装方式)
-----------1 卸载系统自带的msyql包 rpm -qa|grep mysql rpm -e --nodeps mysql-server-5.1.71-1.el6.x86_64 --强制卸 ...
- 环境搭建:Vue环境搭建和项目初始化(ubuntu)
1. 安装node.js(版本6.10.3) 首先确保系统安装来gcc,g++,如果没有则安装: $ sudo apt-get update $ sudo apt-get install gcc ...
- 「小程序JAVA实战」微信小程序简介(一)
转自:https://idig8.com/2018/08/09/xiaochengxu-chuji-01/ 一直想学习小程序,苦于比较忙,加班比较多没时间,其实这都是理由,很多时候习惯了搬砖,习惯了固 ...
- PLSQL链接oracle报错--ORA-12154: TNS: 无法解析指定的连接标识符
D:\install\PLSQL\instantclient_11_2 今天重新安装了oracle 11g,plsql连接oracle时发生报错:ORA-12154: TNS: 无法解析指定的连接标识 ...
- java中FILE类常用API介绍
- textarea标签提示录入剩余字数
textarea标签提示录入剩余字数 <textarea onkeydown="checkMaxInput(this,300)" onkeyup="checkMax ...