Share via


IDisposable korrekt implementieren

Aktualisiert: November 2007

     TypeName

ImplementIDisposableCorrectly

CheckId

CA10634

Kategorie

Microsoft.Design

Unterbrechende Änderung

Nicht unterbrechend

Ursache

IDisposable wurde nicht korrekt implementiert. Zu den möglichen Gründen für dieses Problem gehören:

  • IDisposable wurde in der Klasse erneut implementiert.

  • Finalize wurde erneut überschrieben.

  • Dispose wurde überschrieben.

  • Dispose() ist nicht public, sealed oder mit Dispose bezeichnet.

  • Dispose(bool) ist nicht protected, virtual oder unsealed.

  • In unversiegelten Typen muss Dispose() Dispose(true) aufrufen.

  • Bei unversiegelten Typen ruft die Finalize-Implementierung weder Dispose(bool) noch den Basisklassen-Finalizer noch beide auf.

Bei einem Verstoß gegen eines dieser Muster wird diese Warnung ausgelöst.

Jeder unversiegelte IDisposable-Stammtyp muss eine eigene geschützte virtuelle void Dispose (bool)-Methode bereitstellen. Dispose() muss Dipose(true) und Finalize muss Dispose(false) aufrufen. Wenn Sie einen unversiegelten IDisposable-Stammtyp erstellen, müssen Sie Dispose(bool) definieren und aufrufen.

Regelbeschreibung

Alle IDisposable-Typen müssen das Dispose-Muster korrekt implementieren.

Behandlung von Verstößen

Untersuchen Sie den Code, um festzustellen, durch welche der folgenden Lösungen dieser Verstoß behoben werden kann.

  • Entfernen Sie IDisposable aus der Liste von Schnittstellen, die durch {0} implementiert wurden, und überschreiben Sie stattdessen die Dispose-Implementierung der Basisklasse.

  • Entfernen Sie den Finalizer aus dem Typ {0}, überschreiben Sie Dispose(bool disposing), und platzieren Sie die Finalize-Logik in dem Codepfad, in dem 'disposing' False ist.

  • Entfernen Sie {0}, überschreiben Sie Dispose(bool disposing), und platzieren Sie die Dispose-Logik in dem Codepfad, in dem 'disposing' True ist.

  • Vergewissern Sie sich, dass {0} als public und sealed deklariert ist.

  • Benennen Sie {0} in 'Dispose' um, und vergewissern Sie sich, dass {0} als public und sealed deklariert ist.

  • Vergewissern Sie sich, dass {0} als protected, virtual und unsealed deklariert ist.

  • Ändern Sie {0} so, dass Dispose(true) und anschließend GC.SuppressFinalize in der aktuellen Objektinstanz aufgerufen ('this' oder 'Me' in VB) und anschließend ein Wert zurückgegeben wird.

  • Ändern Sie {0} so, dass Dispose(false) aufgerufen und anschließend ein Wert zurückgegeben wird.

  • Stellen Sie beim Schreiben einer unversiegelten IDisposable-Stammklasse sicher, dass die Implementierung von IDisposable nach dem oben beschriebenen Muster erfolgt.

Wann sollten Warnungen unterdrückt werden?

Unterdrücken Sie keine Warnung dieser Regel.

Beispiel für Pseudocode

Der folgende Pseudocode enthält ein allgemeines Beispiel für die Implementierung von Dispose(bool) in einer Klasse, die verwaltete und systemeigene Ressourcen verwendet:

public class Resource : IDisposable 
{
    private IntPtr nativeResource = Marhsal.AllocHGlobal(100);
    private AnotherResource managedResource = new AnotherResource();

// Dispose() calls Dispose(true)
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
    // NOTE: Leave out the finalizer altogether if this class doesn't 
    // own unmanaged resources itself, but leave the other methods
    // exactly as they are. 
    ~Resource() 
    {
        // Finalizer calls Dispose(false)
        Dispose(false);
    }
    // The bulk of the clean-up code is implemented in Dispose(bool)
    protected virtual void Dispose(bool disposing)
    {
        if (disposing) 
        {
            // free managed resources
            if (managedResource != null)
            {
                managedResource.Dispose();
                managedResource = null;
            }
        }
        // free native resources if there are any.
        if (nativeResource != IntPtr.Zero) 
        {
            Marshal.FreeHGlobal(nativeResource);
            nativeResource = IntPtr.Zero;
        }
    }
}