需要在使用TcpClient的类上实现终结器吗?

时间:2009-02-12 15:27:49

标签: c# idisposable finalizer unmanagedresources

我有一个类(比如MyClass)使用(作为私有字段)一个TcpClient对象。 MyClassIDisposable方法中实施了TcpClient.Close Dispose

我的问题是MyClass还应该实现终结器调用Dispose(bool Disposing)以释放TcpClient’s非托管资源,以防调用代码调用MyClass.Dispose吗?

由于

4 个答案:

答案 0 :(得分:4)

不,你不应该。

因为你永远不应该在终结器中的其他对象上调用方法,所以它可能已经在你的对象之前完成了。

垃圾收集器将调用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.
}

答案 1 :(得分:2)

不,你不应该。

来自this优秀帖子:

  

最终确定是基本的   与结束对象不同   一生。从正确的角度来看   看来,之间没有任何顺序   终结者(特殊情况之外)   对于关键终结者),所以如果你   有两个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);
        }
    }

答案 2 :(得分:1)

不,你不必。 TcpClient是一个围绕非托管套接字的包装类,它的管理方式就是应该处理它。你所做的就足够了。

答案 3 :(得分:0)

是的,你应该 - Microsoft even recommends it

请记住,腰带和吊带代码永远不会让你在凌晨2点被叫到办公室:)