CA1063: Implementera IDisposable korrekt
Property | Värde |
---|---|
Regel-ID | CA1063 |
Title | Implementera IDisposable korrekt |
Kategori | Designa |
Korrigeringen är icke-bakåtkompatibel | Icke-icke-bryta |
Aktiverad som standard i .NET 9 | Nej |
Orsak
Gränssnittet System.IDisposable är inte korrekt implementerat. Möjliga orsaker till detta är:
- IDisposable omimplementeras i klassen.
Finalize
åsidosätts igen.Dispose()
är åsidosatt.- Metoden
Dispose()
är inte offentlig, förseglad eller med namnet Ta bort. Dispose(bool)
är inte skyddat, virtuellt eller oförseglat.- I oförseglade typer
Dispose()
måste anropaDispose(true)
. - För oförseglade typer
Finalize
anropar implementeringen inte antingen eller bådaDispose(bool)
eller basklassens finaliserare.
Brott mot något av dessa mönster utlöser varning CA1063.
Varje oförseglat typ som deklarerar och implementerar IDisposable gränssnittet måste tillhandahålla en egen protected virtual void Dispose(bool)
metod. Dispose()
ska anropa Dispose(true)
, och finalizern ska anropa Dispose(false)
. Om du skapar en oförseglat typ som deklarerar och implementerar IDisposable gränssnittet måste du definiera Dispose(bool)
och anropa det. Mer information finns i Rensa ohanterade resurser (.NET-guide) och Implementera en Dispose-metod.
Som standard tittar den här regeln bara på externt synliga typer, men det kan konfigureras.
Regelbeskrivning
Alla IDisposable typer bör implementera mönstret Kassera korrekt.
Så här åtgärdar du överträdelser
Granska koden och ta reda på vilken av följande lösningar som åtgärdar den här överträdelsen:
Ta bort IDisposable från listan över gränssnitt som implementeras av din typ och åsidosätt basklassen Disponera implementering i stället.
Ta bort finalizern från din typ, åsidosätt Dispose(bool disposing) och placera finaliseringslogik i kodsökvägen där "disposing" är false.
Åsidosätt Dispose(bool disposing) och placera bortskaffandelogik i kodsökvägen där "disposing" är sant.
Kontrollera att Dispose() har deklarerats som offentlig och förseglad.
Byt namn på avyttringsmetoden till Ta bort och se till att den deklareras som offentlig och förseglad.
Kontrollera att Dispose(bool) har deklarerats som skyddat, virtuellt och oförseglat.
Ändra Dispose() så att den anropar Dispose(true), anropar SuppressFinalize sedan på den aktuella objektinstansen (
this
ellerMe
i Visual Basic) och returnerar sedan.Ändra din finalizer så att den anropar Dispose(false) och sedan returnerar.
Om du skapar en oförseglat typ som deklarerar och implementerar IDisposable gränssnittet kontrollerar du att implementeringen av IDisposable följer det mönster som beskrivs tidigare i det här avsnittet.
När du ska ignorera varningar
Ignorera inte en varning från den här regeln.
Kommentar
Du kan se falska positiva varningar från den här regeln om alla följande gäller:
- Du använder Visual Studio 2022 version 17.5 eller senare med en äldre version av .NET SDK, dvs. .NET 6 eller tidigare.
- Du använder analysverktygen från .NET 6 SDK eller en äldre version av analyspaketen, till exempel Microsoft.CodeAnalysis.FxCopAnalyzers.
- Du har attribut för implementeringen
IDispose
.
I det här fallet är det säkert att undertrycka en falsk positiv varning. Falska positiva identifieringar beror på en icke-bakåtkompatibel ändring i C#-kompilatorn. Överväg att använda en nyare analysator som innehåller korrigeringen för falska positiva varningar. Uppgradera till Microsoft.CodeAnalysis.NetAnalyzers version 7.0.0-preview1.22464.1 eller senare eller använd analysverktygen från .NET 7 SDK.
Konfigurera kod för analys
Använd följande alternativ för att konfigurera vilka delar av kodbasen som regeln ska köras på.
Du kan konfigurera det här alternativet för bara den här regeln, för alla regler som gäller för eller för alla regler i den här kategorin (design) som den gäller för. Mer information finns i Konfigurationsalternativ för kodkvalitetsregel.
Inkludera specifika API-ytor
Du kan konfigurera vilka delar av kodbasen som ska köras med den här regeln baserat på deras tillgänglighet. Om du till exempel vill ange att regeln endast ska köras mot den icke-offentliga API-ytan lägger du till följande nyckel/värde-par i en .editorconfig-fil i projektet:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Exempel på pseudokod
Följande pseudokod innehåller ett allmänt exempel på hur Dispose(bool)
bör implementeras i en klass som använder hanterade och inbyggda resurser.
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);
}
}