Нужно реализовать финализатор в классе, использующем TcpClient?

StackOverflow https://stackoverflow.com/questions/541797

Вопрос

У меня есть класс (скажем 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, мертвы одновременно, вы не можете предсказать, какой финализатор завершит первым.Это означает, что у вас не может быть финализатора, который взаимодействует с любыми окончательными объектами, хранящимися в переменных экземпляра.

Это моя эталонная реализация шаблона disposable/finalize с комментариями, объясняющими, когда и что использовать:

/// <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 — это класс-оболочка неуправляемого сокета, и поэтому он управляется так, как он должен быть удален.Того, что вы сделали, достаточно.

Да, ты должен - Microsoft даже рекомендует это.

Просто помните, что код ремня и подтяжек никогда не вызовет вас в офис в 2:00 ночи :)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top