Zoeken…


Opmerkingen

  • Het is aan de klanten van de klasse die IDisposable om ervoor te zorgen dat ze de Dispose methode aanroepen wanneer ze klaar zijn met het object. Er is niets in de CLR dat rechtstreeks in objecten zoekt naar een Dispose 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 eigen Dispose 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 een private bool aan uw klasse toe te voegen en de waarde op true wanneer de methode Dispose 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");
    }
}

Bekijk demo

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


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow