Sök…


Anmärkningar

  • Det är upp till klienter i klassen som implementerar IDisposable att se till att de ringer Dispose när de är färdiga med att använda objektet. Det finns inget i CLR som direkt söker efter objekt efter en Dispose 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 egen Dispose .

  • 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 en private bool till din klass och ställa in värdet till true när Dispose 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");
    }
}

Visa demo

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();
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow