In .NET, unter welchen Umständen sollte ich verwenden GC.SuppressFinalize()
?
Welche(r) Vorteil(e) bringt mir die Anwendung dieser Methode?
In .NET, unter welchen Umständen sollte ich verwenden GC.SuppressFinalize()
?
Welche(r) Vorteil(e) bringt mir die Anwendung dieser Methode?
SuppressFinalize
sollte nur von einer Klasse aufgerufen werden, die einen Finalizer hat. Er teilt dem Garbage Collector (GC) mit, dass this
Objekt wurde vollständig bereinigt.
Die empfohlene IDisposable
Muster, wenn Sie einen Finalizer haben, ist:
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);
}
}
Normalerweise behält die CLR Objekte mit einem Finalizer im Auge, wenn sie erstellt werden (was ihre Erstellung verteuert). SuppressFinalize
teilt dem GC mit, dass das Objekt ordnungsgemäß aufgeräumt wurde und nicht in die Finalizer-Warteschlange gestellt werden muss. Er sieht aus wie ein C++-Destruktor, verhält sich aber nicht wie einer.
Le SuppressFinalize
Optimierung ist nicht trivial, da Ihre Objekte sehr lange in der Finalizer-Warteschlange stehen können. Lassen Sie sich nicht dazu verleiten, die SuppressFinalize
auf andere Objekte, wohlgemerkt. Das ist ein schwerwiegender Fehler, der nur darauf wartet, zu passieren.
Design-Richtlinien informieren uns, dass ein Finalizer nicht notwendig ist, wenn Ihr Objekt IDisposable
, aber wenn Sie einen Finalizer haben, sollten Sie IDisposable
um die deterministische Bereinigung Ihrer Klasse zu ermöglichen.
Die meiste Zeit sollten Sie damit auskommen können IDisposable
um die Ressourcen zu bereinigen. Sie sollten nur dann einen Finalizer benötigen, wenn Ihr Objekt auf nicht verwaltete Ressourcen zugreift und Sie sicherstellen müssen, dass diese Ressourcen bereinigt werden.
Hinweis: Manchmal fügen Programmierer einen Finalizer zu ihren eigenen Debug-Builds hinzu IDisposable
Klassen, um zu prüfen, ob der Code ihre IDisposable
Objekt ordnungsgemäß.
public void Dispose() // Implement IDisposable
{
Dispose(true);
#if DEBUG
GC.SuppressFinalize(this);
#endif
}
#if DEBUG
~MyClass() // the finalizer
{
Dispose(false);
}
#endif
SupressFinalize
teilt dem System mit, dass die Arbeit, die im Finalizer erledigt worden wäre, bereits erledigt ist, so dass der Finalizer nicht aufgerufen werden muss. Aus den .NET-Dokumenten:
Objekte, die t implementieren Schnittstelle implementieren, können diese Methode von der Methode IDisposable.Dispose aufrufen, um zu verhindern, dass der Garbage Collector von Object.Finalize für ein Objekt aufruft, das dies nicht benötigt.
Generell gilt, dass fast alle Dispose()
Methode sollte in der Lage sein, die GC.SupressFinalize()
denn es sollte alles bereinigen, was im Finalizer bereinigt werden würde.
SupressFinalize
ist nur eine Optimierung, die es dem System ermöglicht, das Objekt nicht in die Warteschlange des Finalizer-Threads zu stellen. Eine richtig geschriebene Dispose()
/finalizer sollte mit oder ohne einen Aufruf von GC.SupressFinalize()
.
Dispose(true);
GC.SuppressFinalize(this);
Wenn das Objekt einen Finalizer hat, stellt .net eine Referenz in die Finalisierungswarteschlange.
Da wir den Aufruf Dispose(true)
wird das Objekt gelöscht, so dass wir keine Finalisierungswarteschlange für diese Aufgabe benötigen.
Rufen Sie also GC.SuppressFinalize(this)
Referenz in der Finalisierungswarteschlange entfernen.
Wenn eine Klasse oder etwas von ihr Abgeleitetes den letzten lebenden Verweis auf ein Objekt mit einem Finalizer enthält, dann kann entweder GC.SuppressFinalize(this)
ou GC.KeepAlive(this)
sollte für das Objekt nach jeder Operation aufgerufen werden, die von diesem Finalizer beeinträchtigt werden könnte, um sicherzustellen, dass der Finalizer erst nach Abschluss dieser Operation ausgeführt wird.
Die Kosten für GC.KeepAlive()
y GC.SuppressFinalize(this)
sind in jeder Klasse, die keinen Finalizer hat, im Wesentlichen gleich, und Klassen, die Finalizer haben, sollten generell GC.SuppressFinalize(this)
so dass die Verwendung der letztgenannten Funktion als letzter Schritt von Dispose()
ist vielleicht nicht immer notwendig, aber auch nicht verkehrt.
CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.