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. 【Selenium-WebDriver自学】Selenium-IDE工具特点(二)

    ==================================================================================================== ...

  2. concurrent.futures模块 -----进程池 ---线程池 ---回调

    concurrent.futures模块提供了高度封装的异步调用接口,它内部有关的两个池 ThreadPoolExecutor:线程池,提供异步调用,其基础就是老版的Pool ProcessPoolE ...

  3. 浮动ip原理及简单实现

    原理:https://blog.csdn.net/readiay/article/details/53538085 简单实现:https://www.cnblogs.com/victorwu/p/70 ...

  4. 64位操作系统(Windows 2008 R2 X64)ASP.NET 调用32位Excel,word 出现401 – 未授权: 由于凭据无效,访问被拒绝。

    先确保IIS设置正确,目录权限设置正确. 打开“IIS信息服务管理器”——>选择你发布的网站——>选择功能视图中的“身份验证”——>右键匿名身份验证,选择“编辑”,选择“特定用户“– ...

  5. 09_组件三大属性(3)_refs和事件处理

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. js弹出div层,弹出层页面底部出现UL出现一条线问题

    整个弹出div层,列表满一页时:底部会出现一条横线 原因:ul固定写在页面中了 解决方法: 将ul代码与li列表一样写在js中,如下 var newhtml = '<ul class=" ...

  7. postman 请求种添加用户权限

    1. 打开postman, 在Tests输入以下内容: var jsonData =JSON.parse(responseBody);//获取body中返回的所有参数 postman.setGloba ...

  8. KMP算法next数组求解

    关于KMP算法,许多教材用的是递推式求解,虽然代码简洁,但是有些不好理解,这里我介绍一种迭代求next数组的方法 KMP算法关键部分就是滑动模式串,我们可以每次滑动一个单位,直到出现可能匹配的情况,此 ...

  9. linux 3.10中完成量的使用

    完成量是基于等待队列设计的,所以显然不能在中断上下文使用完成量. struct completion { unsigned int done; wait_queue_head_t wait; }; 我 ...

  10. 1005 继续(3n+1)猜想 (25 分)

    1005 继续(3n+1)猜想 (25)(25 分) - 过期汽水的博客 - CSDN博客https://blog.csdn.net/qq_40167974/article/details/80739 ...