Necessità di attuare un finalizzatore su una classe che utilizza TcpClient?
-
23-08-2019 - |
Domanda
Ho una classe (diciamo MyClass
) che usa (ha come un campo privato) un oggetto TcpClient
. MyClass
implementa IDisposable
chiamata TcpClient.Close
nel metodo Dispose
.
La mia domanda è dovrebbe MyClass
anche attuare un finalizzatore di chiamare Dispose(bool Disposing)
per liberare le risorse non gestite TcpClient’s
nel caso in cui MyClass.Dispose
non è chiamato dal codice chiamante?
Grazie
Soluzione
No non si dovrebbe.
A causa non si dovrebbe mai chiamare un metodo su un altro oggetto in un finalizzatore , che avrebbe potuto essere finalizzato prima l'oggetto.
Il finalizzatore del TcpClient sarà chiamato dal garbage collector, quindi lo lasciò fare.
Il modello in 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.
}
Altri suggerimenti
No non si dovrebbe.
Da questo ottimo post:
La finalizzazione è fondamentalmente diverso da finire un oggetto di tutta la vita. Da un punto di correttezza vista, non c'è nessun ordinamento tra finalizzatori (al di fuori di un caso speciale per finalizzatori critici), quindi se si avere due oggetti che il GC pensa sono morti allo stesso tempo, non si può prevedere quali finalizzatore completerà primo. Questo significa che non si può avere un finalizzatore che interagisce con qualsiasi oggetti finalizable memorizzati in caso variabili.
Questa è la mia implementazione di riferimento del modello finalizzare / usa e getta con i commenti che spiega quando usare cosa:
/// <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);
}
}
No, non c'è bisogno di. TcpClient è una classe wrapper presa gestito e lì viene gestita come dovrebbe essere smaltito. Quello che hai fatto è sufficiente.
Si deve - Microsoft consiglia addirittura .
Basta ricordare che il codice cintura e bretelle non viene mai chiamato in ufficio alle 2:00 AM:)