Udostępnij za pośrednictwem


CA1063: Należy prawidłowo zaimplementować interfejs IDisposable

TypeName

ImplementIDisposableCorrectly

CheckId

CA1063

Kategoria

Microsoft.Design

Zmiana kluczowa

Niekluczowa

Przyczyna

IDisposable nie jest zaimplementowany poprawnie.Przyczyny tego problemu są wymienione poniżej:

  • IDisposable jest ponownie implementowany w klasie.

  • Funkcja Finalize została ponownie zastąpiona.

  • Funkcja Dispose została ponownie zastąpiona.

  • Funkcja Dispose() nie jest publiczna, zamknięta lub nazwana Dispose.

  • Funkcja Dispose(bool) nie jest chroniona, wirtualna lub niezamknięta.

  • W typach niezamkniętych funkcja Dispose() musi wywołać funkcję Dispose(true).

  • Dla typów niezamkniętych implementacja Finalize nie wywołuje funkcji Dispose(bool) lub obu lub finalizatorów klasy.

Naruszenie któregokolwiek z tych wzorców wyzwala to ostrzeżenie.

Każdy niezamknięty typ o bazowym typie IDisposable musi dostarczyć własną wirtualną metodę chronioną void Dispose(bool).Funkcję Dispose() powinna wywołać Dispose(true) i Finalize powinna wywołać Dispose(false).Jeśli tworzysz niezamknięty typ bazowy IDisposable należy zdefiniować Dispose(bool) i wywołać ją.Aby uzyskać więcej informacji, zobacz Oczyszczanie zasobów niezarządzanych w sekcji Design Guidelines for Developing Class LIbraries dokumentacji .NET Framework.

Opis reguły

Wszystkie typy IDisposable powinny poprawnie implementować wzorzec Dispose.

Jak naprawić naruszenia

Należy zbadać kod i określić, które z następujących rozwiązań naprawi to naruszenie.

  • Usuń IDisposable z listy interfejsów, które są implementowane przez {0} i zamiast tego zastąp bazową klasę implementacją Dispose.

  • Usuń finalizator z typu {0}, zastąp Dispose(bool disposing) i umieść logikę finalizacji w ścieżce kodu, gdzie "dispose" ma wartość false.

  • Usuń {0}, zastąp Dispose(bool disposing) i umieść logikę zbycia w ścieżce kodu gdzie "dispose" przyjmuje wartość true.

  • Zapewnij, że {0} jest zadeklarowany jako publiczny i zamknięty.

  • Zmień nazwę {0} na "Dispose" i upewnij się, że jest zadeklarowana jako publiczna i zamknięta.

  • Upewnij się, że {0} jest zadeklarowane jako chronione, wirtualne i niezamknięte.

  • Zmodyfikuj {0} tak, aby go wywoływało Dispose(true), a następnie wywoływało GC.SuppressFinalize na bieżącym wystąpieniu obiektu ('this' lub 'Me' w Visual Basic), a następnie wracało.

  • Zmodyfikuj {0} tak, aby wywoływało Dispose(false), a następnie wracało.

  • Podczas pisania niezamkniętej klasy bazowej IDisposable upewnij się, że implementacja IDisposable wykonana jest zgodnie ze wzorcem opisanym wcześniej w bieżącej sekcji.

Kiedy pominąć ostrzeżenia

Nie należy pomijać ostrzeżenia dotyczącego tej reguły.

Przykład w pseudokodzie

Następujący pseudokod dostarcza ogólny przykład jak Dispose(bool) powiddo być implementowane w klasie, która używa zarówno zarządzanych jak i natywnych zasobów.

public class Resource : IDisposable 
{
    private IntPtr nativeResource = Marshal.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;
        }
    }
}