2009-02-12 16 views
5

Tengo una clase (digamos MyClass) que usa (tiene como campo privado) un objeto TcpClient. MyClass implementa IDisposable llamando al TcpClient.Close en el método Dispose.¿Necesita implementar un finalizador en una clase que usa TcpClient?

Mi pregunta es MyClass debe también implementar un finalizador para llamar Dispose(bool Disposing) para liberar los recursos no administrados TcpClient’s en caso de MyClass.Dispose no es llamado por el código de llamada?

Gracias

Respuesta

4

No, no debería.

Como nunca debe llamar a un método en otro objeto en un finalizador, podría haberse finalizado antes de su objeto.

El finalizador de su TcpClient será llamado por el recolector de basura, así que déjelo hacer.

El patrón en Desechar es:

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

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

Sí que debiera - Microsoft even recommends it.

Sólo recuerde que el código de correa y tirantes nunca se le llamó a la oficina a las 2:00 am :)

1

No, no tiene que hacerlo. TcpClient es una clase contenedora alrededor del socket no administrado y allí se gestiona de la manera en que debería desecharse. Lo que has hecho es suficiente.

2

No, no deberías.

De this excelente post:

Finalización es fundamentalmente diferente de terminando la vida de un objeto. Desde un punto de vista corrección, no existe una ordenación entre finalizadores (fuera de un caso especial para finalizadores críticos), por lo que si tiene dos objetos que el GC piensa están muertos, al mismo tiempo, no se puede predecir cuyo finalizador completará primero . Esto significa que no puede tener un finalizador que interactúe con los objetos finalizables almacenados en las variables de instancia .

Ésta es mi implementación de referencia de la pila/finalizar patrón con comentarios explicando cuándo usar lo que:

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

Cualquier comentario sobre mi * perfecto * (no creo que por un instante, pero es lo mejor para salir;) bienvenida de clase. – ng5000

Cuestiones relacionadas