浅析C# Dispose方法的实现

开发 后端
C# Dispose方法是什么呢?C# Dispose方法的实现是如何的呢?实现的过程中应该注意些什么呢?那么本文就向你介绍到这里,希望对你了解和学习C# Dispose方法有所帮助。

C# Dispose方法的理解是什么呢?类型的Dispose方法应释放它拥有的所有资源。它还应该通过调用其父类型的Dispose方法释放其基类型拥有的所有资源。该父类型的 Dispose 方法应该释放它拥有的所有资源并同样也调用其父类型的 Dispose 方法,从而在整个基类型层次结构中传播此模式。若要确保始终正确地清理资源,Dispose 方法应该可以被多次调用而不引发任何异常。

Dispose 方法应该为它处置的对象调用 GC.SuppressFinalize 方法。如果对象当前在终止队列中,GC.SuppressFinalize 防止其 Finalize 方法被调用。请记住,执行 Finalize 方法会大大减损性能。如果您的 Dispose 方法已经完成了清理对象的工作,那么垃圾回收器就不必再调用对象的 Finalize 方法。

C# Dispose方法的实现时注意

为 System.GC.KeepAlive(System.Object) 方法提供的代码示例演示了强行垃圾回收如何在回收对象的成员仍在执行时引起终结器运行。在较长的Dispose方法末尾***调用KeepAlive方法。

下面的代码示例旨在阐释用于为封装了非托管资源的类实现Dispose方法的建议设计模式。整个 .NET Framework 中都实现了此模式。

资源类通常是从复杂的本机类或 API 派生的,而且必须进行相应的自定义。使用这一代码模式作为创建资源类的一个起始点,并根据封装的资源提供必要的自定义。不能编译该示例,也不能将其直接用于应用程序。

在此示例中,基类 BaseResource 实现可由该类的用户调用的公共 Dispose 方法。而该方法又调用 virtual Dispose(bool disposing) 方法(Visual Basic 中为 virtual Dispose(disposing As Boolean))。根据调用方的标识传递 true 或 false。以虚 Dispose 方法为对象执行适当的清理代码。

Dispose(bool disposing) 以两种截然不同的方案执行。如果 disposing 等于 true,则该方法已由用户的代码直接调用或间接调用,并且可释放托管资源和非托管资源。如果 disposing 等于 false,则该方法已由运行库从终结器内部调用,并且只能释放非托管资源。因为终结器不会以任意特定的顺序执行,所以当对象正在执行其终止代码时,不应引用其他对象。如果正在执行的终结器引用了另一个已经终止的对象,则该正在执行的终结器将失败。

基类提供的 Finalize 方法或析构函数在未能调用 Dispose 的情况下充当防护措施。Finalize 方法调用带有参数的 Dispose 方法,同时传递 false。不应在 Finalize 方法内重新创建 Dispose 清理代码。调用 Dispose(false) 可以优化代码的可读性和可维护性。

类 MyResourceWrapper 阐释如何使用 Dispose 从实现资源管理的类派生。MyResourceWrapper 重写 virtual Dispose(bool disposing) 方法并为其创建的托管和非托管资源提供清理代码。MyResourceWrapper 还对其基类 BaseResource 调用 Dispose 以确保其基类能够适当地进行清理。请注意,派生类 MyResourceWrapper 没有不带参数的 Finalize 方法或 Dispose 方法,因为这两个方法从基类 BaseResource 继承这些参数。

C# Dispose方法的实现时注意

此示例中的 protected Dispose(bool disposing) 方法不强制线程安全,因为无法从用户线程和终结器线程同时调用该方法。另外,使用 BaseResource 的客户端应用程序应从不允许多个用户线程同时调用 protected Dispose(bool disposing) 方法。应用程序或类库的设计原则为:应用程序或类库应只允许一个线程拥有资源的生存期,并且应在不再需要资源时调用 Dispose。根据资源的不同,在处置资源时进行异步线程访问可能会带来安全风险。开发人员应仔细检查自己的代码,以确定***的方法来强制线程安全

C# Dispose方法的实现实例

// Design pattern for the base class.  
// By implementing IDisposable, you are announcing that instances  
// of this type allocate scarce resources.  
public class BaseResource: IDisposable  
{  
// Pointer to an external unmanaged resource.  
private IntPtr handle;  
// Other managed resource this class uses.  
private Component Components;  
// Track whether Dispose has been called.  
private bool disposed = false;  
 
// Constructor for the BaseResource object.  
public BaseResource()  
{  
// Insert appropriate constructor code here.  
}  
 
// Implement IDisposable.  
// Do not make this method virtual.  
// A derived class should not be able to override this method.  
public void Dispose()  
{  
Dispose(true);  
// Take yourself off the Finalization queue   
// to prevent finalization code for this object  
// from executing a second time.  
GC.SuppressFinalize(this);  
}  
 
// 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.  
Components.Dispose();  
}  
// Release unmanaged resources. If disposing is false,   
// only the following code is executed.  
CloseHandle(handle);  
handle = IntPtr.Zero;  
// Note that this is not thread safe.  
// Another thread could start disposing the object  
// after the managed resources are disposed,  
// but before the disposed flag is set to true.  
// If thread safety is necessary, it must be  
// implemented by the client.  
 
}  
disposed = true;  
}  
 
// 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.  
~BaseResource()  
{  
// Do not re-create Dispose clean-up code here.  
// Calling Dispose(false) is optimal in terms of  
// readability and maintainability.  
Dispose(false);  
}  
 
// Allow your Dispose method to be called multiple times,  
// but throw an exception if the object has been disposed.  
// Whenever you do something with this class,   
// check to see if it has been disposed.  
public void DoSomething()  
{  
if(this.disposed)  
{  
throw new ObjectDisposedException();  
}  
}  
}  
 
// Design pattern for a derived class.  
// Note that this derived class inherently implements the   
// IDisposable interface because it is implemented in the base class.  
public class MyResourceWrapper: BaseResource  
{  
// A managed resource that you add in this derived class.  
private ManagedResource addedManaged;  
// A native unmanaged resource that you add in this derived class.  
private NativeResource addedNative;  
private bool disposed = false;  
 
  // Constructor for this object.  
public MyResourceWrapper()  
{  
// Insert appropriate constructor code here.  
}  
 
protected override void Dispose(bool disposing)  
{  
if(!this.disposed)  
{  
try 
{  
if(disposing)  
{  
// Release the managed resources you added in  
// this derived class here.  
addedManaged.Dispose();  
}  
// Release the native unmanaged resources you added  
// in this derived class here.  
CloseHandle(addedNative);  
this.disposed = true;  
}  
finally 
{  
// Call Dispose on your base class.  
base.Dispose(disposing);  
}  
}  
}  
}  
 
// This derived class does not have a Finalize method  
// or a Dispose method without parameters because it inherits   
// them from the base class.  
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.
  • 60.
  • 61.
  • 62.
  • 63.
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83.
  • 84.
  • 85.
  • 86.
  • 87.
  • 88.
  • 89.
  • 90.
  • 91.
  • 92.
  • 93.
  • 94.
  • 95.
  • 96.
  • 97.
  • 98.
  • 99.
  • 100.
  • 101.
  • 102.
  • 103.
  • 104.
  • 105.
  • 106.
  • 107.
  • 108.
  • 109.
  • 110.
  • 111.
  • 112.
  • 113.
  • 114.
  • 115.
  • 116.
  • 117.
  • 118.
  • 119.
  • 120.
  • 121.
  • 122.
  • 123.
  • 124.
  • 125.
  • 126.
  • 127.
  • 128.
  • 129.
  • 130.
  • 131.
  • 132.
  • 133.
  • 134.
  • 135.
  • 136.

C# Dispose方法的实现以及C# Dispose方法的一些基本内容就向你介绍到这里,希望对你了解和学习C# Dispose方法有所帮助。

【编辑推荐】

  1. C#窗体设计操作浅析
  2. C#窗体设计器开发实例详解
  3. C#窗体移动实例解析
  4. C#透明窗体代码详解
  5. C#透明窗体及按钮的效果浅析
责任编辑:仲衡 来源: MSDN
相关推荐

2009-09-07 09:53:01

C# DisposeDispose方法

2009-08-31 16:33:28

C#调用Dispose

2009-09-11 10:59:06

Effective C调用Dispose()

2011-03-29 09:14:49

Dispose模式C#

2009-09-11 09:15:06

C# get方法

2009-08-20 16:15:19

C# 匿名方法

2009-08-10 17:36:17

C#扩展方法

2009-09-10 14:52:55

C# get

2009-06-16 13:22:59

SqlConnecti

2009-08-17 16:59:47

C#转义字符双引号

2009-08-28 15:52:23

C#利用sharpzi

2009-09-02 17:24:44

C#关机代码

2009-08-17 17:56:32

C# 枚举

2009-09-10 09:10:17

C# TextBox换

2009-08-26 09:54:45

C#打印预览C#打印

2009-09-27 10:43:13

C#合并多个WORD文

2009-09-01 18:29:24

C#实现多个接口

2009-08-31 16:48:02

C#实现IDispos

2009-09-02 15:34:37

C#实现插件构架

2009-08-14 16:02:50

C#启动windows
点赞
收藏

51CTO技术栈公众号