我有一个MyClass
使用(作为私有字段)TcpClient
对象的类(比如说)。MyClass
实现方法中的IDisposable
调用。TcpClient.Close
Dispose
我的问题是MyClass
还应该实现一个终结器来调用Dispose(bool Disposing)
以释放TcpClient’s
非托管资源,以防MyClass.Dispose
调用代码不调用它?
谢谢
我有一个MyClass
使用(作为私有字段)TcpClient
对象的类(比如说)。MyClass
实现方法中的IDisposable
调用。TcpClient.Close
Dispose
我的问题是MyClass
还应该实现一个终结器来调用Dispose(bool Disposing)
以释放TcpClient’s
非托管资源,以防MyClass.Dispose
调用代码不调用它?
谢谢
不,你不应该。
因为你不应该在终结器中调用其他对象的方法,所以它可能在你的对象之前被终结。
你的 TcpClient 的终结器将被垃圾收集器调用,所以让他去做吧。
Dispose 中的模式是:
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// dispose managed resources (here your TcpClient)
}
// dispose your unmanaged resources
// handles etc using static interop methods.
}
不,你不应该。
从这个优秀的帖子:
终结与结束对象的生命周期有着根本的不同。从正确性的角度来看,终结器之间没有顺序(关键终结器的特殊情况除外),因此如果您有两个 GC 认为同时死亡的对象,您无法预测哪个终结器将首先完成。这意味着您不能拥有与存储在实例变量中的任何可终结对象交互的终结器。
这是我对一次性/最终确定模式的参考实现,其中包含解释何时使用什么的注释:
/// <summary>
/// Example of how to implement the dispose pattern.
/// </summary>
public class PerfectDisposableClass : IDisposable
{
/// <summary>
/// Type constructor.
/// </summary>
public PerfectDisposableClass()
{
Console.WriteLine( "Constructing" );
}
/// <summary>
/// Dispose method, disposes resources and suppresses finalization.
/// </summary>
public void Dispose()
{
Dispose( true );
GC.SuppressFinalize(this);
}
/// <summary>
/// Disposes resources used by class.
/// </summary>
/// <param name="disposing">
/// True if called from user code, false if called from finalizer.
/// When true will also call dispose for any managed objects.
/// </param>
protected virtual void Dispose(bool disposing)
{
Console.WriteLine( "Dispose(bool disposing) called, disposing = {0}", disposing );
if (disposing)
{
// Call dispose here for any managed objects (use lock if thread safety required), e.g.
//
// if( myManagedObject != null )
// {
// myManagedObject.Dispose();
// myManagedObject = null;
// }
}
}
/// <summary>
/// Called by the finalizer. Note that if <see cref="Dispose()"/> has been called then finalization will
/// have been suspended and therefore never called.
/// </summary>
/// <remarks>
/// This is a safety net to ensure that our resources (managed and unmanaged) are cleaned up after usage as
/// we can guarantee that the finalizer will be called at some point providing <see cref="Dispose()"/> is
/// not called.
/// Adding a finalizer, however, IS EXPENSIVE. So only add if using unmanaged resources (and even then try
/// and avoid a finalizer by using <see cref="SafeHandle"/>).
/// </remarks>
~PerfectDisposableClass()
{
Dispose(false);
}
}
不,你不必。TcpClient 是一个围绕非托管套接字的包装类,因此它以应该被处理的方式进行管理。你所做的就足够了。
是的,你应该这样做——微软甚至推荐它。
请记住,腰带和吊带代码永远不会让您在凌晨 2:00 被叫到办公室:)