CA1063: IDisposable correct implementeren

Eigenschap Waarde
Regel-id CA1063
Titel IDisposable correct implementeren
Categorie Ontwerpen
Fix kan brekend of niet-brekend zijn Niet-brekend
Standaard ingeschakeld in .NET 10 Nee
Toepasselijke talen C# en Visual Basic

Oorzaak

De System.IDisposable interface is niet correct geïmplementeerd. Mogelijke redenen hiervoor zijn:

  • IDisposable wordt opnieuw gebruikt in de klasse.
  • Finalize wordt opnieuw overschreven.
  • Dispose() wordt overschreven.
  • De Dispose() methode is niet openbaar, is niet sealed en heeft niet de naam Dispose.
  • Dispose(bool) is niet beveiligd, virtueel of niet-verzegeld.
  • In niet-verzegelde typen moet Dispose()Dispose(true) aanroepen.
  • Voor niet-verzegelde typen roept de Finalize implementatie geen of beide Dispose(bool) of de finalizer van de basisklasse aan.

Schending van een van deze patronen activeert waarschuwing CA1063.

Elk niet-verzegeld type dat de IDisposable interface declareert en implementeert, moet een eigen protected virtual void Dispose(bool) methode bieden. Dispose() moet Dispose(true) aanroepen, en de finalizer moet Dispose(false) aanroepen. Als u een niet-verzegeld type maakt dat de IDisposable interface declareert en implementeert, moet u Dispose(bool) definiëren en aanroepen. Zie de handleiding onbeheerde resources (.NET) opschonen en een verwijderingsmethode implementeren voor meer informatie.

Deze regel kijkt standaard alleen naar extern zichtbare typen, maar dit kan worden geconfigureerd.

Beschrijving van regel

Alle IDisposable typen moeten het verwijderingspatroon correct implementeren.

Hoe schendingen op te lossen

Controleer uw code en bepaal welke van de volgende oplossingen deze schending verhelpt:

  • Verwijder IDisposable uit de lijst met interfaces die door uw type zijn geïmplementeerd en overschrijf in plaats daarvan de implementatie van de basisklasse Verwijderen.

  • Verwijder de finalizer uit uw type, override Dispose(bool disposing), en plaats de finalisatielogica in het codepad waar 'disposing' onwaar is.

  • Overschrijf Dispose(bool disposing) en plaats de verwijderingslogica in het codepad waar 'disposing' waar is.

  • Zorg ervoor dat Dispose() is gedeclareerd als openbaar en verzegeld.

  • Wijzig de naam van de methode naar Dispose en zorg ervoor dat deze is gedeclareerd als public en sealed.

  • Zorg ervoor dat Dispose(bool) is gedeclareerd als beveiligd, virtueel en niet-verzegeld.

  • Wijzig Dispose() zodat deze Dispose(true) aanroept, het huidige objectexemplaar SuppressFinalize (of Me in Visual Basic) aanroept, en vervolgens retourneert.

  • Pas uw finalizer aan zodat deze Dispose(false) aanroept en vervolgens terugkeert.

  • Als u een niet-verzegeld type maakt dat de IDisposable interface declareert en implementeert, moet u ervoor zorgen dat de implementatie van IDisposable het patroon volgt dat eerder in deze sectie wordt beschreven.

Wanneer waarschuwingen onderdrukken

Een waarschuwing van deze regel niet onderdrukken.

Notitie

U ziet mogelijk vals-positieve waarschuwingen van deze regel als aan alle van de volgende wordt voldaan:

  • U gebruikt Visual Studio 2022 versie 17.5 of hoger met een oudere versie van de .NET SDK, dat wil zeggen .NET 6 of eerder.
  • U gebruikt de analyses van de .NET 6 SDK of een oudere versie van de analysepakketten, zoals Microsoft.CodeAnalysis.FxCopAnalyzers.
  • U hebt kenmerken voor uw IDispose implementatie.

In dit geval is het veilig om een foutpositieve waarschuwing te onderdrukken. De fout-positieven zijn te wijten aan een wijziging die fouten veroorzaakt in de C#-compiler. Overweeg om een nieuwere analyser te gebruiken die de oplossing bevat voor de valse positieve waarschuwingen. Voer een upgrade uit naar Microsoft.CodeAnalysis.NetAnalyzers versie 7.0.0-preview1.22464.1 of hoger of gebruik de analyses van de .NET 7 SDK.

Code configureren om te analyseren

Gebruik de volgende optie om te configureren op welke onderdelen van uw codebase deze regel moet worden uitgevoerd.

U kunt deze optie configureren voor alleen deze regel, voor alle regels waarop deze van toepassing is, of voor alle regels in deze categorie (ontwerp) waarop deze van toepassing is. Zie de configuratieopties voor de codekwaliteitsregel voor meer informatie.

Specifieke API-oppervlakken opnemen

U kunt configureren op welke onderdelen van uw codebase deze regel moet worden uitgevoerd, op basis van hun toegankelijkheid, door de optie api_surface in te stellen. Als u bijvoorbeeld wilt opgeven dat de regel alleen moet worden uitgevoerd op het niet-openbare API-oppervlak, voegt u het volgende sleutel-waardepaar toe aan een .editorconfig-bestand in uw project:

dotnet_code_quality.CAXXXX.api_surface = private, internal

Notitie

Vervang het XXXX deel van CAXXXX door de id van de toepasselijke regel.

Voorbeeld van pseudocode

De volgende pseudocode biedt een algemeen voorbeeld van hoe Dispose(bool) moet worden geïmplementeerd in een klasse die gebruikmaakt van beheerde en systeemeigen resources.

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

Zie ook