Suche…


Bemerkungen

  • Es ist IDisposable Clients der Klasse, die IDisposable implementiert, um sicherzustellen, dass sie die Dispose Methode aufrufen, wenn sie das Objekt IDisposable verwendet haben. Die CLR enthält nichts, das Objekte direkt nach einer Dispose Methode sucht, die Dispose 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 eigene Dispose Methode implementieren.

  • Es wird empfohlen, die Klasse gegen mehrere Aufrufe von Dispose zu Dispose , obwohl sie idealerweise nur einmal aufgerufen werden sollte. Dies kann erreicht werden, indem Sie Ihrer Klasse eine private bool Variable hinzufügen und den Wert auf true wenn die Dispose 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");
    }
}

Demo anzeigen

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


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow