C# Language
IDisposable-Schnittstelle
Suche…
Bemerkungen
Es ist
IDisposable
Clients der Klasse, dieIDisposable
implementiert, um sicherzustellen, dass sie dieDispose
Methode aufrufen, wenn sie das ObjektIDisposable
verwendet haben. Die CLR enthält nichts, das Objekte direkt nach einerDispose
Methode sucht, dieDispose
werden soll.Es ist nicht erforderlich, einen Finalizer zu implementieren, wenn Ihr Objekt nur verwaltete Ressourcen enthält. Rufen Sie
Dispose
für alle Objekte auf, die Ihre Klasse verwendet, wenn Sie Ihre eigeneDispose
Methode implementieren.Es wird empfohlen, die Klasse gegen mehrere Aufrufe von
Dispose
zuDispose
, obwohl sie idealerweise nur einmal aufgerufen werden sollte. Dies kann erreicht werden, indem Sie Ihrer Klasse eineprivate bool
Variable hinzufügen und den Wert auftrue
wenn dieDispose
Methode ausgeführt wird.
In einer Klasse, die nur verwaltete Ressourcen enthält
Verwaltete Ressourcen sind Ressourcen, die der Garbage Collector der Laufzeitumgebung kennt und unter deren Kontrolle steht. In der BCL sind viele Klassen verfügbar, beispielsweise eine SqlConnection
, die eine Wrapper-Klasse für eine nicht verwaltete Ressource ist. Diese Klassen implementieren bereits die IDisposable
Schnittstelle - es liegt an Ihrem Code, sie zu bereinigen, wenn Sie fertig sind.
Es ist nicht erforderlich, einen Finalizer zu implementieren, wenn Ihre Klasse nur verwaltete Ressourcen enthält.
public class ObjectWithManagedResourcesOnly : IDisposable
{
private SqlConnection sqlConnection = new SqlConnection();
public void Dispose()
{
sqlConnection.Dispose();
}
}
In einer Klasse mit verwalteten und nicht verwalteten Ressourcen
Es ist wichtig, dass die Finalisierung verwaltete Ressourcen ignoriert. Der Finalizer läuft in einem anderen Thread - es ist möglich, dass die verwalteten Objekte zum Zeitpunkt der Finalisierung nicht mehr vorhanden sind. Die Implementierung einer geschützten Dispose(bool)
-Methode ist eine gängige Praxis, um sicherzustellen, dass für verwaltete Ressourcen keine Dispose
Methode von einem Finalizer aufgerufen wird.
public class ManagedAndUnmanagedObject : IDisposable
{
private SqlConnection sqlConnection = new SqlConnection();
private UnmanagedHandle unmanagedHandle = Win32.SomeUnmanagedResource();
private bool disposed;
public void Dispose()
{
Dispose(true); // client called dispose
GC.SuppressFinalize(this); // tell the GC to not execute the Finalizer
}
protected virtual void Dispose(bool disposeManaged)
{
if (!disposed)
{
if (disposeManaged)
{
if (sqlConnection != null)
{
sqlConnection.Dispose();
}
}
unmanagedHandle.Release();
disposed = true;
}
}
~ManagedAndUnmanagedObject()
{
Dispose(false);
}
}
IDisposable, entsorgen
.NET Framework definiert eine Schnittstelle für Typen, die eine Abreißmethode erfordern:
public interface IDisposable
{
void Dispose();
}
Dispose()
wird hauptsächlich für die Bereinigung von Ressourcen verwendet, beispielsweise für nicht verwaltete Referenzen. Es kann jedoch auch nützlich sein, die Entsorgung anderer Ressourcen zu erzwingen, obwohl diese verwaltet werden. Anstatt darauf zu warten, dass der GC schließlich auch Ihre Datenbankverbindung bereinigt, können Sie sicherstellen, dass dies in Ihrer eigenen Dispose()
Implementierung der Dispose()
.
public void Dispose()
{
if (null != this.CurrentDatabaseConnection)
{
this.CurrentDatabaseConnection.Dispose();
this.CurrentDatabaseConnection = null;
}
}
Wenn Sie direkt auf nicht verwaltete Ressourcen wie nicht verwaltete Zeiger oder win32-Ressourcen zugreifen müssen, erstellen Sie eine Klasse, die von SafeHandle
und verwenden Sie die Konventionen / Tools dieser Klasse.
In einer geerbten Klasse mit verwalteten Ressourcen
Es ist IDisposable
üblich, dass Sie eine Klasse erstellen, die IDisposable
implementiert, und dann Klassen ableiten, die auch verwaltete Ressourcen enthalten. Es wird empfohlen, die Dispose
Methode mit dem virtual
Schlüsselwort zu kennzeichnen, damit Clients alle Ressourcen bereinigen können, die sie besitzen.
public class Parent : IDisposable
{
private ManagedResource parentManagedResource = new ManagedResource();
public virtual void Dispose()
{
if (parentManagedResource != null)
{
parentManagedResource.Dispose();
}
}
}
public class Child : Parent
{
private ManagedResource childManagedResource = new ManagedResource();
public override void Dispose()
{
if (childManagedResource != null)
{
childManagedResource.Dispose();
}
//clean up the parent's resources
base.Dispose();
}
}
Schlüsselwort verwenden
Wenn ein Objekt die IDisposable
Schnittstelle implementiert, kann es innerhalb der using
Syntax erstellt werden:
using (var foo = new Foo())
{
// do foo stuff
} // when it reaches here foo.Dispose() will get called
public class Foo : IDisposable
{
public void Dispose()
{
Console.WriteLine("dispose called");
}
}
using
ist syntatic Zucker für einen try/finally
Block; Die obige Verwendung würde grob bedeuten:
{
var foo = new Foo();
try
{
// do foo stuff
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}