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. [Unity插件]Lua行为树(五):装饰节点Repeater

    Repeater:重复执行子节点,直到一定次数 特点如下: 1.执行次数可以是无限循环,也可以是固定次数 2.一般来说,子节点的执行返回状态不会影响Repeater节点,但可以设置当子节点返回失败时, ...

  2. 转:SQL 操作结果集 -并集、差集、交集、结果集排序

    为了配合测试,特地建了两个表,并且添加了一些测试数据,其中重复记录为东吴的人物. 表:Person_1魏国人物 表:Person_2蜀国人物 A.Union形成并集 Union可以对两个或多个结果集进 ...

  3. win7 CMD登录本机MySQL数据库管理

  4. 【Excel技能】字符串包含某字符串个数?替换许多组字符串?

    =len(单元格A)-len(substitute(单元格A,某字符串,)) 原理:将某字符串替换成空,前后字符串长即为减去的这个字符串长度,这个字符串出现个数=前后字符串长度之差/这个字符串长度 = ...

  5. 1.python进程、线程、多线程

    2018-07-16 1.进程 简单理解:进程就是一段程序执行的过程. 广义理解:进程就是一个具有一定独立功能的程序关于某个数据集合的一次运行活动. 进程是cpu调度和分配的基本的分配单元,也是基本的 ...

  6. 《算法》第四章部分程序 part 2

    ▶ 书中第四章部分程序,加上自己补充的代码,随机生成各类无向图 ● 随机生成无向图 package package01; import edu.princeton.cs.algs4.StdOut; i ...

  7. python中的expandtabs、\t

    expandtabs()将tab转换成空格,默认1个tab转成8个空格,\t制表符代表一个tab,我们也可以自定义转换成几个空格 举个例子: 1 a = "hello\tworld" ...

  8. 白鹭引擎 - 碰撞检测 ( hitTestPoint )

    1, 矩形碰撞检测 class Main extends egret.DisplayObjectContainer { /** * Main 类构造器, 初始化的时候自动执行, ( 子类的构造函数必须 ...

  9. [记录] CSS 左边元素定长,右边元素获得剩余长度

    情景:左边元素定长,右边元素获得剩余长度 1. 左边设置浮动,右边元素宽度auto,可以不设置,默认auto,然后设置margin-left:左边元素宽度 <ul class="ent ...

  10. JEECG-P3首个开源插件诞生!CMS网站插件 Jeecg-p3-biz-cms1.0版本发布!

    Jeecg-P3-Biz-Cms   ( JEECG 首个微服务插件,支持小程序的CMS系统) 是基于JEECG-P3 微服务框架开发的CMS建站系统,可轻量级集成进jeecg系统,定制各类网站模板, ...