Share via


CA2213: Disponibla fält ska kasseras

Property Värde
Regel-ID CA2213
Rubrik Disponibla fält ska kasseras
Kategori Användning
Korrigeringen är icke-bakåtkompatibel Icke-icke-bryta
Aktiverad som standard i .NET 8 Nej

Orsak

En typ som implementerar System.IDisposable deklarerar fält som är av typer som även implementerar IDisposable. Metoden Dispose för fältet anropas inte av Dispose metoden för deklareringstypen.

Regelbeskrivning

En typ ansvarar för att ta bort alla dess ohanterade resurser. Regel CA2213 kontrollerar om en engångstyp (det vill säga en som implementerar IDisposable) T deklarerar ett fält F som är en instans av en engångstyp FT. För varje fält F som har tilldelats ett lokalt skapat objekt inom metoderna eller initierarna av den innehållande typen Tförsöker regeln hitta ett anrop till FT.Dispose. Regeln söker igenom de metoder som anropas av T.Dispose och en nivå lägre (det vill: de metoder som anropas av metoderna som anropas av T.Dispose).

Kommentar

Förutom specialfallen utlöses endast regel CA2213 för fält som tilldelas ett lokalt skapat engångsobjekt inom den innehållande typens metoder och initialiserare. Om objektet skapas eller tilldelas utanför typen Tutlöses inte regeln. Detta minskar bruset för fall där den innehållande typen inte äger ansvaret för att ta bort objektet.

Särskilda fall

Regel CA2213 kan också utlösas för fält av följande typer även om objektet de tilldelas inte skapas lokalt:

Att skicka ett objekt av någon av dessa typer till en konstruktor och sedan tilldela det till ett fält anger en överföring av ägarskap till den nyligen konstruerade typen. Det innebär att den nyligen konstruerade typen nu ansvarar för att ta bort objektet. Om objektet inte tas bort sker en överträdelse av CA2213.

Så här åtgärdar du överträdelser

Om du vill åtgärda ett brott mot den här regeln anropar du Dispose fält som är av typer som implementerar IDisposable.

När du ska ignorera varningar

Det är säkert att ignorera en varning från den här regeln om:

  • Den flaggade typen ansvarar inte för att frigöra resursen som innehas av fältet (det vill: typen har inte ägarskap för bortskaffande)
  • Anropet till Dispose sker på en djupare anropsnivå än regelkontrollerna
  • ägarskapet för fälten inte innehas av den innehållande typen.

Ignorera en varning

Om du bara vill förhindra en enda överträdelse lägger du till förprocessordirektiv i källfilen för att inaktivera och aktiverar sedan regeln igen.

#pragma warning disable CA2213
// The code that's violating the rule is on this line.
#pragma warning restore CA2213

Om du vill inaktivera regeln för en fil, mapp eller ett projekt anger du dess allvarlighetsgrad till none i konfigurationsfilen.

[*.{cs,vb}]
dotnet_diagnostic.CA2213.severity = none

Mer information finns i Så här utelämnar du kodanalysvarningar.

Exempel

Följande kodfragment visar en typ TypeA som implementerar IDisposable.

public class TypeA : IDisposable
{
    protected virtual void Dispose(bool disposing)
    {
        if (disposing)
        {
            // Dispose managed resources
        }

        // Free native resources
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    // Disposable types implement a finalizer.
    ~TypeA()
    {
        Dispose(false);
    }
}

Följande kodfragment visar en typ TypeB som bryter mot regeln CA2213 genom att deklarera ett fält aFieldOfADisposableType som en engångstyp (TypeA) och inte anropa Dispose i fältet.

public class TypeB : IDisposable
{
    // Assume this type has some unmanaged resources.
    TypeA aFieldOfADisposableType = new TypeA();
    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            // Dispose of resources held by this instance.

            // Violates rule: DisposableFieldsShouldBeDisposed.
            // Should call aFieldOfADisposableType.Dispose();

            disposed = true;
            // Suppress finalization of this disposed instance.
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }
    }

    public void Dispose()
    {
        if (!disposed)
        {
            // Dispose of resources held by this instance.
            Dispose(true);
        }
    }

    // Disposable types implement a finalizer.
    ~TypeB()
    {
        Dispose(false);
    }
}

Om du vill åtgärda överträdelsen anropar du Dispose() disponibelt fält:

protected virtual void Dispose(bool disposing)
{
   if (!disposed)
   {
      // Dispose of resources held by this instance.
      aFieldOfADisposableType.Dispose();

      disposed = true;

      // Suppress finalization of this disposed instance.
      if (disposing)
      {
          GC.SuppressFinalize(this);
      }
   }
}

Se även