Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
| Vlastnost | Hodnota |
|---|---|
| ID pravidla | CA1063 |
| Název | Implementujte IDisposable správně |
| Kategorie | Návrh |
| Oprava, která může být destruktivní nebo nedestruktivní | Nezlomitelný |
| Povoleno ve výchozím nastavení v .NET 10 | Ne |
| Příslušné jazyky | C# a Visual Basic |
Příčina
Rozhraní System.IDisposable není implementováno správně. Mezi možné důvody patří:
- IDisposable je reimplementován ve třídě.
-
Finalizeje přepsaný znovu. -
Dispose()je přepsáno. - Metoda
Dispose()není veřejná, zapečetěná nebo pojmenovaná Dispose. -
Dispose(bool)není chráněn, virtuální ani nezapečetěný. - V nezapečetěných typech musí
Dispose()volatDispose(true). - Pro nezapečetěné typy
Finalizeimplementace nevolá aniDispose(bool), ani finalizátor základní třídy.
Porušení některého z těchto vzorů aktivuje upozornění CA1063.
Každý nezapečetěný typ, který deklaruje a implementuje IDisposable rozhraní, musí poskytovat vlastní protected virtual void Dispose(bool) metodu.
Dispose() by měla volat Dispose(true), a finalizátor by měl volat Dispose(false). Pokud vytvoříte nezapečetěný typ, který deklaruje a implementuje rozhraní IDisposable, musíte definovat Dispose(bool) a toto volání provést. Další informace naleznete v tématu Vyčištění nespravovaných prostředků (průvodce .NET) a Implementace metody Dispose.
Ve výchozím nastavení toto pravidlo sleduje jenom externě viditelné typy, ale dá se konfigurovat.
Popis pravidla
Všechny IDisposable typy by měly správně implementovat vzor Dispose.
Jak opravit porušení
Prozkoumejte kód a určete, která z následujících řešení toto porušení opraví:
Odeberte IDisposable ze seznamu rozhraní, která jsou implementována vaším typem, a místo toho přepište implementaci metody Dispose v základní třídě.
Odeberte finalizér z vašeho typu, přepište Dispose(bool disposing) a umístěte logiku finalizace do části kódu, kde je 'disposing' rovno false.
Přepište metodu Dispose(bool disposing) a vložte logiku pro uvolnění do části kódu, kde je 'disposing' pravda.
Ujistěte se, že dispose() je deklarována jako veřejná a zapečetěná.
Přejmenujte metodu dispose na Dispose a ujistěte se, že je deklarována jako veřejná a zapečetěná.
Ujistěte se, že dispose(bool) je deklarován jako chráněný, virtuální a nezapečetěný.
Upravte Dispose() tak, aby volal Dispose(true), pak volá SuppressFinalize na aktuální instanci objektu (
this, neboMev jazyce Visual Basic), a pak se vrátí.Upravte finalizátor tak, aby zavolal Dispose(false) a pak se vrátil.
Pokud vytvoříte nezapečetěný typ, který deklaruje a implementuje IDisposable rozhraní, ujistěte se, že implementace IDisposable následuje vzor popsaný výše v této části.
Kdy potlačit upozornění
Nepotlačujte upozornění na toto pravidlo.
Poznámka:
Falešně pozitivní upozornění z tohoto pravidla se můžou zobrazit, pokud platí všechny tyto skutečnosti:
- Používáte Sadu Visual Studio 2022 verze 17.5 nebo novější se starší verzí sady .NET SDK, tj. .NET 6 nebo starší.
- Používáte analyzátory ze sady .NET 6 SDK nebo starší verze balíčků analyzátoru, například Microsoft.CodeAnalysis.FxCopAnalyzers.
- Ve své
IDisposeimplementaci máte atributy.
V tomto případě je bezpečné potlačit falešně pozitivní upozornění. Falešně pozitivní výsledky jsou způsobeny zásadní změnou kompilátoru jazyka C#. Zvažte použití novějšího analyzátoru, který obsahuje opravu falešně pozitivních upozornění. Upgradujte na Microsoft.CodeAnalysis.NetAnalyzers verze 7.0.0-preview1.22464.1 nebo novější nebo použijte analyzátory ze sady .NET 7 SDK.
Konfigurace kódu pro analýzu
Pomocí následující možnosti nakonfigurujte, ve kterých částech základu kódu se má toto pravidlo spouštět.
Tuto možnost můžete nakonfigurovat jenom pro toto pravidlo, pro všechna pravidla, která platí, nebo pro všechna pravidla v této kategorii (Návrh), na která platí. Další informace naleznete v tématu Možnosti konfigurace pravidla kvality kódu.
Zahrnutí konkrétních povrchů rozhraní API
Nastavením možnosti api_surface můžete nakonfigurovat, na kterých částech základu kódu se má toto pravidlo spouštět na základě jejich přístupnosti. Pokud chcete například určit, že pravidlo by se mělo spouštět jenom na neveřejné ploše rozhraní API, přidejte do souboru .editorconfig v projektu následující pár klíč-hodnota:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Poznámka:
Nahraďte XXXX část CAXXXX ID příslušného pravidla.
Příklad pseudokódu
Následující pseudokód poskytuje obecný příklad toho, jak by mělo být Dispose(bool) implementováno ve třídě, jež využívá spravované a nativní prostředky.
public class Resource : IDisposable
{
private bool isDisposed;
private IntPtr nativeResource = Marshal.AllocHGlobal(100);
private AnotherResource managedResource = new AnotherResource();
// Dispose() calls Dispose(true)
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// The bulk of the clean-up code is implemented in Dispose(bool)
protected virtual void Dispose(bool disposing)
{
if (isDisposed) return;
if (disposing)
{
// free managed resources
managedResource.Dispose();
}
// free native resources if there are any.
if (nativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
isDisposed = true;
}
// NOTE: Leave out the finalizer altogether if this class doesn't
// own unmanaged resources, but leave the other methods
// exactly as they are.
~Resource()
{
// Finalizer calls Dispose(false)
Dispose(false);
}
}