CA2213: Pola usuwalne powinny zostać usunięte

Właściwości Wartość
Identyfikator reguły CA2213
Stanowisko Pola możliwe do likwidacji należy likwidować
Kategoria Użycie
Poprawka powodująca niezgodność lub niezgodność Niezgodność
Domyślnie włączone na platformie .NET 8 Nie.

Przyczyna

Typ implementujący System.IDisposable deklaruje pola, które są typami, które również implementują IDisposableelement . Dispose Metoda pola nie jest wywoływana przez Dispose metodę typu deklarowanego.

Opis reguły

Typ jest odpowiedzialny za usuwanie wszystkich niezarządzanych zasobów. Reguła CA2213 sprawdza, czy typ jednorazowego (czyli taki, który implementuje IDisposable) T deklaruje pole F , które jest wystąpieniem typu FTjednorazowego . Dla każdego pola F przypisanego lokalnie utworzonego obiektu w ramach metod lub inicjatorów typu zawierającego Treguła próbuje zlokalizować wywołanie metody FT.Dispose. Reguła wyszukuje metody wywoływane przez T.Dispose i jeden poziom niższy (czyli metody wywoływane przez metody o nazwie T.Dispose).

Uwaga

Poza przypadkami specjalnymi reguła CA2213 jest uruchamiana tylko w przypadku pól, które są przypisane lokalnie do obiektu jednorazowego w ramach metod i inicjatorów typu zawierającego. Jeśli obiekt zostanie utworzony lub przypisany poza typem T, reguła nie zostanie wyzwolona. Zmniejsza to szum w przypadkach, w których typ zawierający nie ponosi odpowiedzialności za usunięcie obiektu.

Przypadki szczególne

Reguła CA2213 może również być uruchamiana dla pól następujących typów, nawet jeśli przypisany obiekt nie jest tworzony lokalnie:

Przekazanie obiektu jednego z tych typów do konstruktora, a następnie przypisanie go do pola wskazuje przeniesienie własności usuwania do nowo skonstruowanego typu. Oznacza to, że nowo skonstruowany typ jest teraz odpowiedzialny za usuwanie obiektu. Jeśli obiekt nie jest usuwany, występuje naruszenie CA2213.

Jak naprawić naruszenia

Aby naprawić naruszenie tej reguły, wywołaj Dispose pola, które są typami, które implementują IDisposableelement .

Kiedy pomijać ostrzeżenia

Można bezpiecznie pominąć ostrzeżenie z tej reguły, jeśli:

  • Typ oflagowany nie jest odpowiedzialny za zwolnienie zasobu przechowywanego przez pole (czyli typ nie ma własności usuwania)
  • Wywołanie wykonywane Dispose na wyższym poziomie wywołania niż sprawdza reguła
  • własność usuwania pól nie jest przechowywana przez typ zawierający.

Pomijanie ostrzeżenia

Jeśli chcesz po prostu pominąć pojedyncze naruszenie, dodaj dyrektywy preprocesora do pliku źródłowego, aby wyłączyć, a następnie ponownie włączyć regułę.

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

Aby wyłączyć regułę dla pliku, folderu lub projektu, ustaw jego ważność na none w pliku konfiguracji.

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

Aby uzyskać więcej informacji, zobacz Jak pominąć ostrzeżenia dotyczące analizy kodu.

Przykład

Poniższy fragment kodu przedstawia typ TypeA implementujący IDisposableelement .

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

Poniższy fragment kodu przedstawia typ TypeB , który narusza regułę CA2213, deklarując pole aFieldOfADisposableType jako typ jednorazowy (TypeA) i nie wywołując Dispose pola.

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

Aby naprawić naruszenie, wywołaj Dispose() pole jednorazowe:

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

Zobacz też