Es gibt viele falsche Informationen über IDisposable. Es ist ein PATTERN, das hilft, das zu erreichen, was früher über einen Destruktor in C++ erreicht wurde. Das Problem ist, dass in .NET die Zerstörung eines Objekts nicht deterministisch ist (es passiert nicht automatisch, wenn ein Objekt den Gültigkeitsbereich verlässt, sondern zum Zeitpunkt der Garbage Collection, die sich in einem separaten Thread mit niedriger Priorität befindet).
Sie müssen Dispose nicht implementieren, es sei denn, Sie haben eine Ressource, die auf irgendeine Weise freigegeben werden muss. Wenn beispielsweise Ihre privaten Datenmitglieder Dispose implementieren, sollten Sie wahrscheinlich auch Dispose implementieren und Dispose für diese privaten Mitglieder in Ihrem Dispose aufrufen. Ebenso sollten Sie alle PInvoke-Handles in Dispose freigeben.
Auch die Dispose-Methode wird bei der Garbage Collection NICHT automatisch für Sie aufgerufen. Dies ist das größte Stück Fehlinformation. Sie müssen Dispose von Ihrem Destruktor (C#) oder Finalize (VB.NET) aufrufen. Hier ist ein gutes Muster Entsorgen für die Umsetzung:
public class Foo : IDisposable
{
public Foo()
{
// Allocate some resource here
}
~Foo()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
private void Dispose(bool disposing)
{
// De-allocate resource here
if (disposing)
GC.SuppressFinalize(this);
}
}
Der Grund, dass Sie anrufen GC.SupressFinalize ist, dass, wenn das Objekt einen Finalizer hat, das Objekt tatsächlich auf die nächste GC Generation gefördert werden, weil es zu nennen hat Schließen Sie das erste Mal ab, wenn der GC ausgeführt wird, und können Sie Ihr Objekt erst freigeben, wenn die Finalisierung abgeschlossen ist. Daher wird der Speicher erst beim zweiten Durchlauf des GC freigegeben. Wenn Sie Dispose manuell aufrufen, können Sie den Finalizer überspringen, sodass Ihr Objekt beim ersten Durchlauf des GC freigegeben wird.
Um den größtmöglichen Nutzen aus Entsorgen zu erhalten, verwenden Sie die Verwendung von keword:
using (Foo f = new Foo())
{
// Do something with Foo
}
Dies ist genau das gleiche wie wenn Sie dies geschrieben hatte:
Foo f;
try
{
f = new Foo();
// Do something with Foo
}
finally
{
f.Dispose();
}
Einige Leute ein setzen möchten Boolean in ihrer Klasse namens _disposed, und dann überprüfen Sie, dass Bool während jedes Methodenaufrufs und eine Ausnahme auslösen, wenn Sie versuchen, eine Methode für ein Objekt aufzurufen, nachdem Dispose aufgerufen wird. Für interne Projektklassen halte ich diesen Overkill im Allgemeinen für sinnvoll, aber es könnte eine gute Sache sein, wenn Sie eine Bibliothek für den Verbrauch von Drittanbietern erstellen.
Ich würde auch sehr empfehlen einen Artikel mit dem Titel "IDisposable: Was Ihre Mutter Ihnen nie über Ressourcenfreigabe erzählt" unter http://www.codeproject.com/KB/dotnet/IDisposable.aspx - obwohl es Ihnen das Gefühl geben könnte, dass die Verwendung von IDisposable absolut korrekt ist, ist es fast hoffnungslos. –