C# Language
IDisposable interface
Zoeken…
Opmerkingen
Het is aan de klanten van de klasse die
IDisposable
om ervoor te zorgen dat ze deDispose
methode aanroepen wanneer ze klaar zijn met het object. Er is niets in de CLR dat rechtstreeks in objecten zoekt naar eenDispose
methode die kan worden aangeroepen.Het is niet nodig om een finalizer te implementeren als uw object alleen beheerde bronnen bevat. Zorg ervoor dat u
Dispose
voor alle objecten die uw klas gebruikt wanneer u uw eigenDispose
methode implementeert.Het wordt aanbevolen om de klas te beveiligen tegen meerdere oproepen om te
Dispose
, hoewel deze idealiter slechts één keer moet worden aangeroepen. Dit kan worden bereikt door eenprivate bool
aan uw klasse toe te voegen en de waarde optrue
wanneer de methodeDispose
is uitgevoerd.
In een klasse die alleen beheerde bronnen bevat
Beheerde bronnen zijn bronnen waarvan de afvalverzamelaar van de runtime op de hoogte is en die hij onder controle heeft. Er zijn veel klassen beschikbaar in de BCL, zoals een SqlConnection
die een wrapper-klasse is voor een onbeheerde bron. Deze klassen implementeren al de IDisposable
interface - het is aan uw code om ze op te ruimen als u klaar bent.
Het is niet nodig om een finalizer te implementeren als uw klas alleen beheerde bronnen bevat.
public class ObjectWithManagedResourcesOnly : IDisposable
{
private SqlConnection sqlConnection = new SqlConnection();
public void Dispose()
{
sqlConnection.Dispose();
}
}
In een klas met beheerde en onbeheerde bronnen
Het is belangrijk om bij het voltooien van beheerde bronnen te negeren. De finalizer draait op een andere thread - het is mogelijk dat de beheerde objecten niet meer bestaan tegen de tijd dat de finalizer wordt uitgevoerd. Het implementeren van een beveiligde Dispose(bool)
methode Dispose(bool)
is een gangbare praktijk om ervoor te zorgen dat beheerde bronnen niet over hun Dispose
methode worden geroepen vanuit een finalizer.
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, weggooien
.NET Framework definieert een interface voor typen waarvoor een verwijderingsmethode nodig is:
public interface IDisposable
{
void Dispose();
}
Dispose()
wordt voornamelijk gebruikt voor het opschonen van bronnen, zoals onbeheerde referenties. Het kan echter ook nuttig zijn om andere middelen af te dwingen, ook al worden ze beheerd. In plaats van te wachten tot de GC uiteindelijk ook uw databaseverbinding opruimt, kunt u ervoor zorgen dat dit gebeurt in uw eigen Dispose()
-implementatie.
public void Dispose()
{
if (null != this.CurrentDatabaseConnection)
{
this.CurrentDatabaseConnection.Dispose();
this.CurrentDatabaseConnection = null;
}
}
Wanneer u rechtstreeks toegang moet hebben tot onbeheerde bronnen zoals onbeheerde pointers of win32-bronnen, maakt u een klasse die SafeHandle
van SafeHandle
en gebruikt u de conventies / hulpmiddelen van die klasse om dit te doen.
In een geërfde klasse met beheerde bronnen
Het is vrij gebruikelijk dat u een klasse maakt die IDisposable
en vervolgens klassen IDisposable
die ook beheerde bronnen bevatten. Het wordt aanbevolen om de methode Dispose
te markeren met het virtual
sleutelwoord, zodat clients de bronnen die ze bezitten kunnen opschonen.
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();
}
}
met behulp van trefwoord
Wanneer een object implementeert IDisposable
interface kunnen worden gemaakt binnen het using
syntax:
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
is syntatische suiker voor een try/finally
blok; het bovenstaande gebruik zou zich ongeveer vertalen in:
{
var foo = new Foo();
try
{
// do foo stuff
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}