Delen via


CA1063: IDisposable correct implementeren

Eigenschappen Weergegeven als
Regel-id CA1063
Titel IDisposable correct implementeren
Categorie Ontwerpen
Oplossing is brekend of niet-brekend Niet-brekend
Standaard ingeschakeld in .NET 8 Nee

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, verzegeld of met de naam Dispose.
  • Dispose(bool) is niet beveiligd, virtueel of niet-verzegeld.
  • In niet-verzegelde typen Dispose() moet worden aangeroepen Dispose(true).
  • 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 worden aangeroepen Dispose(true)en de finalizer moet worden aangeroepen Dispose(false). Als u een niet-verzegeld type maakt dat de IDisposable interface declareert en implementeert, moet u deze definiëren Dispose(bool) 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.

Schendingen oplossen

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, overschrijf Verwijdering (verwijderen van bool) en plaats de finalisatielogica in het codepad waar 'verwijderen' onwaar is.

  • Override Dispose(bool disponeren) en plaats de verwijderingslogica in het codepad waar 'verwijderen' waar is.

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

  • Wijzig de naam van de verwijderingsmethode om te verwijderen en zorg ervoor dat deze is gedeclareerd als openbaar en verzegeld.

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

  • Wijzig Dispose() zodat deze Dispose(true) aanroept, roept vervolgens SuppressFinalize het huidige objectexemplaren (thisof Me in Visual Basic) aan en retourneert vervolgens.

  • Pas uw finalizer aan zodat deze Verwijdering (onwaar) aanroept en vervolgens wordt geretourneerd.

  • 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 fout-positieve waarschuwingen van deze regel als alle volgende van toepassing zijn:

  • 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 fout-positieve waarschuwing te onderdrukken. De fout-positieven zijn te wijten aan een wijziging die fouten veroorzaakt in de C#-compiler. Overweeg om een nieuwere analyse te gebruiken die de oplossing voor de fout-positieve waarschuwingen bevat. 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 instellen op welke onderdelen van uw codebase deze regel moet worden uitgevoerd, op basis van hun toegankelijkheid. 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

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