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