Pergunta

Eu tenho uma classe (MyClass digamos) que usa (tem como um campo particular) um objeto TcpClient. implementos MyClass IDisposable chamando TcpClient.Close no método Dispose.

A minha pergunta é deve MyClass também implementar um finalizador para Dispose(bool Disposing) chamada para liberar os recursos não gerenciados TcpClient’s em caso MyClass.Dispose não é chamado pelo código de chamada?

Graças

Foi útil?

Solução

Não, você não deve.

Como você nunca deve chamar um método em um outro objeto em um finalizador , que poderia ter sido finalizado antes de seu objeto.

O finalizador de sua TcpClient será chamado pelo coletor de lixo, então deixá-lo fazer.

O padrão de Descarte é:

protected virtual void Dispose(bool disposing)
{
   if (disposing)
   { 
      // dispose managed resources (here your TcpClient)
   }

   // dispose your unmanaged resources 
   // handles etc using static interop methods.
}

Outras dicas

Não, você não deve.

De este excelente post :

A finalização é fundamentalmente diferente de acabar com um objeto de tempo de vida. Do ponto exatidão de vista, não há nenhuma ordem entre finalizadores (fora de um caso especial para finalizadores críticos), então se você tem dois objetos que o GC pensa estão mortos, ao mesmo tempo, você não pode prever quais finalizador completará primeiro. Isto significa que você não pode ter um finalizador que interage com qualquer finalizable objectos armazenados na instância variáveis.

Esta é a minha implementação de referência do padrão descartável / finalize com comentários explicando quando usar o:

/// <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);
        }
    }

Não, você não tem que. TcpClient é uma classe invólucro em torno do soquete não gerenciado e não para ele é gerido da forma como deve ser descartado. O que você tem feito é suficiente.

Sim, você deveria - Microsoft recomenda ainda que .

Basta lembrar que o código de cinto-e-suspensórios nunca se você ligou para o escritório às 2:00 AM:)

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top