CA2213: Pola usuwalne powinny zostać usunięte
Właściwości | Wartość |
---|---|
Identyfikator reguły | CA2213 |
Tytuł | 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 9 | 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 FT
jednorazowego . Dla każdego pola F
przypisanego lokalnie utworzonego obiektu w ramach metod lub inicjatorów typu zawierającego T
reguł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);
}
}
}