C# Language
IDisponerbart gränssnitt
Sök…
Anmärkningar
Det är upp till klienter i klassen som implementerar
IDisposable
att se till att de ringerDispose
när de är färdiga med att använda objektet. Det finns inget i CLR som direkt söker efter objekt efter enDispose
att åberopa.Det är inte nödvändigt att implementera en finaliserare om ditt objekt endast innehåller hanterade resurser. Var noga med att ringa
Dispose
alla objekt som din klass använder när du implementerar din egenDispose
.Det rekommenderas att klassen är säker mot flera samtal för att
Dispose
, även om den helst bör ringas en gång. Detta kan uppnås genom att lägga till enprivate bool
till din klass och ställa in värdet tilltrue
närDispose
har körts.
I en klass som endast innehåller hanterade resurser
Hanterade resurser är resurser som runtime sopersamlare är medveten om och under kontroll av. Det finns många klasser tillgängliga i BCL, till exempel en SqlConnection
som är en omslagsklass för en ostyrd resurs. Dessa klasser implementerar redan det IDisposable
gränssnittet - det är upp till din kod att rensa upp dem när du är klar.
Det är inte nödvändigt att implementera en finaliserare om din klass endast innehåller hanterade resurser.
public class ObjectWithManagedResourcesOnly : IDisposable
{
private SqlConnection sqlConnection = new SqlConnection();
public void Dispose()
{
sqlConnection.Dispose();
}
}
I en klass med hanterade och okontrollerade resurser
Det är viktigt att låta slutförandet ignorera hanterade resurser. Finaliseraren körs på en annan tråd - det är möjligt att de hanterade objekten inte finns längre när finaliseraren körs. Implementering av en skyddad Dispose(bool)
är en vanlig praxis för att säkerställa att hanterade resurser inte har sin Dispose
som anropas från en slutbehandlare.
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);
}
}
IDisponerbar, kassera
.NET Framework definierar ett gränssnitt för typer som kräver en rivningsmetod:
public interface IDisposable
{
void Dispose();
}
Dispose()
används främst för att rensa upp resurser, som obehöriga referenser. Det kan emellertid också vara användbart att tvinga avyttra andra resurser även om de hanteras. Istället för att vänta på att GC så småningom också kommer att rensa upp din databasanslutning, kan du se till att det görs i din egen Dispose()
-implementering.
public void Dispose()
{
if (null != this.CurrentDatabaseConnection)
{
this.CurrentDatabaseConnection.Dispose();
this.CurrentDatabaseConnection = null;
}
}
När du måste få direkt åtkomst till obehöriga resurser, som till exempel icke-hanterade pekare eller win32-resurser, skapar du en klass som ärver från SafeHandle
och använder klassens konventioner / verktyg för att göra det.
I en ärvd klass med hanterade resurser
Det är ganska vanligt att du kan skapa en klass som implementerar IDisposable
och sedan härleda klasser som också innehåller hanterade resurser. Det rekommenderas att markera Dispose
metoden med det virtual
nyckelordet så att klienter har möjlighet att rensa alla resurser de kan äga.
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();
}
}
med hjälp av nyckelord
När ett objekt implementerar IDisposable
gränssnitt kan det skapas inom 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
är syntatiskt socker för ett try/finally
block; ovanstående användning skulle grovt översätta till:
{
var foo = new Foo();
try
{
// do foo stuff
}
finally
{
if (foo != null)
((IDisposable)foo).Dispose();
}
}