Share via


CA1063: Implementera IDisposable korrekt

Property Värde
Regel-ID CA1063
Rubrik Implementera IDisposable korrekt
Kategori Designa
Korrigeringen är icke-bakåtkompatibel Icke-icke-bryta
Aktiverad som standard i .NET 8 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 anropa Dispose(true).
  • För oförseglade typer Finalize anropar implementeringen inte antingen eller båda Dispose(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 (thiseller Me 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);
    }
}

Se även