Implementing a Dispose method

0、Dispose() and Dispose(Boolean)

  The IDisposable interface requires the implementation of a single parameterless method, Dispose. However, the dispose pattern requires two Dispose methods to be implemented:

  • A public non-virtual (NonInheritable in Visual Basic) IDisposable.Dispose implementation that has no parameters.

  • A protected virtual (Overridable in Visual Basic) Dispose method whose signature is:

    

1、Dispose() has a standard implementation, The Dispose method performs all object cleanup, so the garbage collector no longer needs to call the objects' Object.Finalizeoverride.

  实现System.IDsiposable.Dispose()方法。不能将此方法设置为virtual,子类不能override此方法。此方法的实现必须为如下代码。

     // Implement IDisposable.
// Do not make this method virtual.
// A derived class should not be able to override this method.
public void Dispose()
{
Dispose(true);
// This object will be cleaned up by the Dispose method.
// Therefore, you should call GC.SupressFinalize to
// take this object off the finalization queue
// and prevent finalization code for this object
// from executing a second time.
GC.SuppressFinalize(this);
}

2、实现析构函数(Finalize)。析构函数必须实现为以下代码。

     // Use C# destructor syntax for finalization code.
// This destructor will run only if the Dispose method
// does not get called.
// It gives your base class the opportunity to finalize.
// Do not provide destructors in types derived from this class.
~MyResource()
{
// Do not re-create Dispose clean-up code here.
// Calling Dispose(false) is optimal in terms of
// readability and maintainability.
Dispose(false);
}

3、实现virtual Dispose(bool disposing)方法,必须为protected。如果dispoing为true,说明从Dipose()方法调用而来;如果为false,说明从析构函数(Finalize)调用而来。在析构函数中,不能再使用引用类型(Ref)成员类型,所以只处理unmanaged resource的释放即可;而在Dipose()调用过程中,managed res & unmanaged res都要释放。

  最后,添加一个成员变量disposed来标记是否已经释放过。

     // Dispose(bool disposing) executes in two distinct scenarios.
// If disposing equals true, the method has been called directly
// or indirectly by a user's code. Managed and unmanaged resources
// can be disposed.
// If disposing equals false, the method has been called by the
// runtime from inside the finalizer and you should not reference
// other objects. Only unmanaged resources can be disposed.
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// Dispose managed resources.
component.Dispose();
} // Call the appropriate methods to clean up
// unmanaged resources here.
// If disposing is false,
// only the following code is executed.
CloseHandle(handle);
handle = IntPtr.Zero; // Note disposing has been done.
disposed = true; }
}

3.1、Here's the general pattern for implementing the dispose pattern for a derived class that overrides Object.Finalize:

  A class derived from a class that implements the IDisposable interface shouldn't implement IDisposable, because the base class implementation of IDisposable.Dispose is inherited by its derived classes.

 using System;

 class DerivedClass : BaseClass
{
// Flag: Has Dispose already been called?
bool disposed = false; // Protected implementation of Dispose pattern.
protected override void Dispose(bool disposing)
{
if (disposed)
return; if (disposing) {
// Free any other managed objects here.
//
} // Free any unmanaged objects here.
//
disposed = true; // Call the base class implementation.
base.Dispose(disposing);
} ~DerivedClass()
{
Dispose(false);
}
}

4、An object must also call the Dispose method of its base class if the base class implements IDisposable.

  如果基类有Dispose()方法,子类必须的Dispose()必须调用基类的Dispose()。

5、什么时候需要Dispose()?

  1)包含Disposable对象的容器类需要实现Dipose,而不需要实现Finalize()。因为清空一个容器,并不表明需要释放unmanged resource。

  2)自身包含unmanged resource的类需实现Dispose、Finalize。

6、DO throw an ObjectDisposedException from any member that cannot be used after the object has been disposed of.

  当调用一个已经Disposed对象时,抛出 ObjectDisposedException。

public class DisposableResourceHolder : IDisposable {
bool disposed = false;
SafeHandle resource; // handle to a resource public void DoSomething(){
if(disposed) throw new ObjectDisposedException(...);
// now call some native methods using the resource
...
}
protected virtual void Dispose(bool disposing){
if(disposed) return;
// cleanup
...
disposed = true;
}
}

7、一些C#自带类库的Close()语言与Dispose()语义是一样的。

public class Stream : IDisposable {
IDisposable.Dispose(){
Close();
}
public void Close(){
Dispose(true);
GC.SuppressFinalize(this);
}
}

参考:

1、https://docs.microsoft.com/en-us/dotnet/api/system.idisposable.dispose?view=netframework-4.7.1

2、https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern

Implementing a Dispose method的更多相关文章

  1. 有关Dispose,Finalize,GC.SupressFinalize函数-托管与非托管资源释放的模式

    //这段代码来自官方示例,删除了其中用处不大的细节using System; using System.ComponentModel; /*** * 这个模式搞的这么复杂,目的是:不管使用者有没有手动 ...

  2. 实现 Dispose 方法

    实现 Dispose 方法 MSDN 类型的 Dispose 方法应释放它拥有的所有资源.它还应该通过调用其父类型的 Dispose 方法释放其基类型拥有的所有资源.该父类型的 Dispose 方法应 ...

  3. JS魔法堂:定义页面的Dispose方法——[before]unload事件启示录

    前言  最近实施的同事报障,说用户审批流程后直接关闭浏览器,操作十余次后系统就报用户会话数超过上限,咨询4A同事后得知登陆后需要显式调用登出API才能清理4A端,否则必然会超出会话上限.  即使在页面 ...

  4. Simple Factory vs. Factory Method vs. Abstract Factory【简单工厂,工厂方法以及抽象工厂的比较】

    I ran into a question on stackoverflow the other day that sort of shocked me. It was a piece of code ...

  5. 定义页面的Dispose方法:[before]unload事件启示录

    前言 最近实施的同事报障,说用户审批流程后直接关闭浏览器,操作十余次后系统就报用户会话数超过上限,咨询4A同事后得知登陆后需要显式调用登出API才能清理4A端,否则必然会超出会话上限. 即使在页面上增 ...

  6. [Javascript + rxjs] Using the map method with Observable

    Like an array, Observable has a map method that allows us to transform a sequence into a new Observa ...

  7. Balanced and stabilized quicksort method

    The improved Quicksort method of the present invention utilizes two pointers initialized at opposite ...

  8. Dispose模式释放非托管资源

    实现方式用的是设计模式里的模板模式,基类先搭好框架,子类重写void Dispose(bool disposing) 即可. 需要注意的是基类的Finalize函数也就是析构函数调用的是虚函数void ...

  9. 调用SqlCommand或SqlDataAdapter的Dispose方法,是否会关闭绑定的SqlConnection?(转载)

    1. Does SqlCommand.Dispose close the connection? 问 Can I use this approach efficiently? using(SqlCom ...

随机推荐

  1. ROS进阶学习笔记(11)- Turtlebot Navigation and SLAM - ROSMapModify - ROS地图修改

    ROS进阶学习笔记(11)- Turtlebot Navigation and SLAM - 2 - MapModify地图修改 We can use gmapping model to genera ...

  2. java判断字符串中是否包含中文 过滤中文

    package com.test; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Test ...

  3. esxI开启虚拟化

    开启esxi的ssh服务 http://blog.51cto.com/7385147/1891513 6.7通过浏览器登陆开启ssh服务,然后再用Xshell登陆esxi服务器,然后修改内容 开启虚拟 ...

  4. N的多次方Python实现

    N的多次方描述编写一个程序,计算输入数字N的0次方到5次方结果,并依次输出这6个结果,输出结果间用空格分隔.其中:N是一个整数或浮点数.print()函数可以同时输出多个信息,采用如下方法可以使用空格 ...

  5. linux 显示系统执行的进程

    ps -a  显示所有的进程信息 -u 以用户的形式显示系统进程 -x  显示后台进程运行的参数 netstat  -anp |more 查看端口 查看开放的端口 vim/etc/sysconfig/ ...

  6. [ilink32 Error] Fatal: Unable to open file 'SDDEBUG.OBJ'

    [ilink32 Error] Fatal: Unable to open file 'SDDEBUG.OBJ' 这个路径NativeXml407\general\sdDebug.pas找不到了 修正 ...

  7. 我要带徒弟学写JAVA架构,引路架构师之路(Jeecg开源社区)

    带徒弟学JAVA架构(Jeecg社区)      Java程序员如何打破工作2,3年的瓶颈问题,如何更上一层楼?      太多的巧合,让我接触到了开源,通过JEECG与很多朋友交流后,让我有了帮助别 ...

  8. day13-文件操作

    1.打开与关闭 1.1.open() close()我们使用 open() 函数打开文件.这个函数将返回一个文件对象,我们对文件的读写都将使用这个对象.open() 函数需要三个参数,第一个参数是文件 ...

  9. Dubbo的优化 --- 开发时使用

    开发时的三个优化: 1.开发者在本地开发的时候启动Dubbo比较麻烦,所以采用直接连接的配置: 2.开发者本地开发时会打断点调试,会超过Dubbo默认的超时时间1s,所以需要全局设置超时时间: 3.开 ...

  10. 尚硅谷redis学习8-事务

    是什么? 能干嘛? 常用命令 案例说明 1.正常执行 2.放弃事务 3.全部放弃(全体连坐) 4.只抛弃错误(冤头债主) 5.watch监控 悲观锁 悲观锁(Pessimistic Lock), 顾名 ...