Quando dovrei usare GC.SuppressFinalize ()?

In .NET, in quali circostanze dovrei utilizzare GC.SuppressFinalize() ?

Che vantaggio usi questo metodo per me?

SuppressFinalize deve essere chiamato solo da una class che ha un finalizzatore. Sta informando il Garbage Collector (GC) che this object è stato completamente ripulito.

Il modello IDisposable consigliato quando si ha un finalizzatore è:

 public class MyClass : IDisposable { private bool disposed = false; protected virtual void Dispose(bool disposing) { if (!disposed) { if (disposing) { // called via myClass.Dispose(). // OK to use any private object references } // Release unmanaged resources. // Set large fields to null. disposed = true; } } public void Dispose() // Implement IDisposable { Dispose(true); GC.SuppressFinalize(this); } ~MyClass() // the finalizer { Dispose(false); } } 

Normalmente, il CLR mantiene le tabs sugli oggetti con un finalizzatore quando vengono creati (rendendoli più costosi da creare). SuppressFinalize dice al GC che l’object è stato ripulito correttamente e non ha bisogno di entrare nella coda del finalizzatore. Sembra un distruttore C ++, ma non agisce in alcun modo come uno.

L’ottimizzazione di SuppressFinalize non è banale, poiché i tuoi oggetti possono vivere a lungo in attesa sulla coda del finalizzatore. Non essere tentato di chiamare SuppressFinalize su altri oggetti. Questo è un difetto grave che aspetta di accadere.

Le linee guida di progettazione ci informano che un finalizzatore non è necessario se il tuo object implementa IDisposable, ma se hai un finalizzatore devi implementare IDisposable per consentire la pulizia deterministica della tua class.

La maggior parte delle volte dovresti essere in grado di cavarcanvas con IDisposable per ripulire le risorse. È necessario disporre di un finalizzatore solo quando l’object è trattenuto su risorse non gestite e è necessario garantire la pulizia di tali risorse.

Nota: a volte i programmatori aggiungono un finalizzatore per eseguire il debug di build delle proprie classi IDisposable per verificare che il codice abbia disposto correttamente il loro object IDisposable.

  public void Dispose() // Implement IDisposable { Dispose(true); #if DEBUG GC.SuppressFinalize(this); #endif } #if DEBUG ~MyClass() // the finalizer { Dispose(false); } #endif 

stai dicendo al sistema che qualsiasi lavoro sarebbe stato fatto nel finalizzatore è già stato fatto, quindi non è necessario chiamare il finalizzatore. Dai documenti .NET:

Gli oggetti che implementano l’interfaccia IDisposable possono chiamare questo metodo dal metodo IDisposable.Dispose per impedire al garbage collector di chiamare Object.Finalize su un object che non lo richiede.

In generale, la maggior parte dei metodi Dispose () dovrebbe essere in grado di chiamare GC.SupressFinalize (), perché dovrebbe ripulire tutto ciò che verrebbe ripulito nel finalizzatore.

SupressFinalize è solo qualcosa che fornisce un’ottimizzazione che consente al sistema di non preoccuparsi di eseguire il routing dell’object al thread del finalizzatore. Un Dispose () / finalizzatore correttamente scritto dovrebbe funzionare correttamente con o senza una chiamata a GC.SupressFinalize ().

Questo metodo deve essere chiamato sul metodo Dispose degli oggetti che implementa l’IDisposable, in questo modo il GC non chiamerebbe il finalizzatore un’altra volta se qualcuno chiama il metodo Dispose.

Vedi: http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx

  Dispose(true); GC.SuppressFinalize(this); 

Se l’object ha finalizzatore, .net mette un riferimento nella coda di finalizzazione

Dato che abbiamo chiamato Dispose (ture), cancella l’object, quindi non abbiamo bisogno della coda di finalizzazione per fare questo lavoro.

Quindi chiama GC.SuppressFinalize (this) remove reference nella coda di finalizzazione.

Se una class, o qualcosa da esso derivato, può contenere l’ultimo riferimento live a un object con un finalizzatore, GC.SuppressFinalize(this) o GC.KeepAlive(this) devono essere richiamati sull’object dopo ogni operazione che potrebbe essere influenzato negativamente da quel finalizzatore, assicurando così che il finalizzatore non venga eseguito fino a quando l’operazione non viene completata.

Il costo di GC.KeepAlive() e GC.SuppressFinalize(this) sono essenzialmente gli stessi in qualsiasi class che non ha un finalizzatore e le classi che hanno i finalizzatori dovrebbero in genere chiamare GC.SuppressFinalize(this) , quindi usare quest’ultimo funziona come l’ultimo passo di Dispose() potrebbe non essere sempre necessario, ma non sarà sbagliato.