6

オブジェクトを使用する(プライベートフィールドとして持つ)クラス(たとえばMyClass)がありTcpClientます。メソッドでの呼び出しをMyClass実装します。IDisposableTcpClient.CloseDispose

私の質問は、呼び出し元のコードによって呼び出されない場合に備えて、アンマネージ リソースを解放するMyClassために呼び出すファイナライザーも実装する必要がありますか?Dispose(bool Disposing)TcpClient’sMyClass.Dispose

ありがとう

4

4 に答える 4

4

いいえ、すべきではありません。

finalizer で他のオブジェクトのメソッドを呼び出してはならないため、オブジェクトの前にファイナライズされている可能性があります。

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.
}
于 2009-02-12T15:31:57.833 に答える
2

いいえ、すべきではありません。

この素晴らしい投稿から:

ファイナライズは、オブジェクトの存続期間を終了することとは根本的に異なります。正確性の観点から、ファイナライザー間の順序はありません(重要なファイナライザーの特別な場合を除く)。したがって、GCが同時に死んでいると考える2つのオブジェクトがある場合、どちらのファイナライザーが最初に完了するかを予測することはできません。これは、インスタンス変数に格納されているファイナライズ可能なオブジェクトと相互作用するファイナライザーを使用できないことを意味します。

これは、使い捨て/ファイナライズパターンのリファレンス実装であり、いつ何を使用するかを説明するコメントが付いています。

/// <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);
        }
    }
于 2009-02-12T15:36:45.250 に答える
1

いいえ、する必要はありません。TcpClientは、アンマネージソケットのラッパークラスであり、そのため、廃棄する方法で管理されます。あなたがしたことで十分です。

于 2009-02-12T15:34:22.603 に答える
0

はい、そうすべきです。Microsoft も推奨しています。

ベルトとサスペンダーのコードでは、午前 2 時にオフィスに呼び出されることはありません:)

于 2009-02-12T15:29:38.323 に答える