Нужно реализовать финализатор в классе, который использует TcpClient? - PullRequest
5 голосов
/ 12 февраля 2009

У меня есть класс (скажем, MyClass), который использует (имеет в качестве частного поля) объект TcpClient. MyClass реализует IDisposable вызов TcpClient.Close в методе Dispose.

Мой вопрос: должен ли MyClass также реализовать финализатор для вызова Dispose(bool Disposing) для освобождения неуправляемых ресурсов TcpClient’s в случае, если MyClass.Dispose не вызван вызывающим кодом?

Спасибо

Ответы [ 4 ]

4 голосов
/ 12 февраля 2009

Нет, не надо.

Поскольку вы никогда не должны вызывать метод другого объекта в финализаторе , он мог быть завершен до вашего объекта.

Финализатор вашего 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.
}
2 голосов
/ 12 февраля 2009

Нет, не надо.

С это отличный пост:

Финализация принципиально отличается от окончания объекта продолжительность жизни. С точки зрения правильности вид, между заказами нет финализаторы (вне особого случая для критических финализаторов), так что если вы есть два объекта, которые думает 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);
        }
    }
1 голос
/ 12 февраля 2009

Нет, ты не обязан. TcpClient - это класс-оболочка для неуправляемого сокета, который управляется так, как он должен быть расположен. То, что вы сделали, достаточно.

0 голосов
/ 12 февраля 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...