CA2213: Uvolnitelné pole by mělo být uvolněno
Vlastnost | Hodnota |
---|---|
ID pravidla | CA2213 |
Název | Uvolnitelná pole by měla být uvolněna |
Kategorie | Využití |
Oprava způsobující chybu nebo chybu způsobující chybu | Nenarušující |
Povoleno ve výchozím nastavení v .NET 8 | No |
Příčina
Typ, který implementuje deklaruje System.IDisposable pole, která jsou typy, které také implementují IDisposable. Dispose Metoda pole není volána Dispose metodou deklarujícího typu.
Popis pravidla
Typ zodpovídá za vyřazení všech nespravovaných prostředků. Pravidlo CA2213 zkontroluje, jestli typ na jedno použití (tj. ten, který implementuje IDisposable) T
deklaruje pole F
, které je instancí jednorázového typu FT
. Pro každé pole F
, které je přiřazen místně vytvořený objekt v rámci metod nebo inicializátorů obsahujícího typu T
, se pravidlo pokusí najít volání FT.Dispose
. Pravidlo hledá metody volané podle T.Dispose
a jednu úroveň nižší (to znamená metody volané metodami T.Dispose
).
Poznámka:
Kromě zvláštních případů se pravidlo CA2213 aktivuje pouze pro pole, která jsou přiřazena místně vytvořeného uvolnitelného objektu v rámci metod a inicializátorů typu. Pokud je objekt vytvořen nebo přiřazen mimo typ T
, pravidlo se neaktivuje. To snižuje šum v případech, kdy typ obsahujícího objektu nevlastní odpovědnost za likvidaci objektu.
Zvláštní případy
Pravidlo CA2213 se také může aktivovat pro pole následujících typů, i když se objekt, který jsou přiřazený, nevytvoří místně:
Předání objektu jednoho z těchto typů konstruktoru a jeho přiřazení k poli označuje převod vlastnictví na nově vytvořený typ. To znamená, že nově vytvořený typ je nyní zodpovědný za likvidaci objektu. Pokud objekt není odstraněn, dojde k porušení CA2213.
Jak opravit porušení
Chcete-li opravit porušení tohoto pravidla, zavolejte Dispose pole, která jsou typu, které implementují IDisposable.
Kdy potlačit upozornění
Upozornění z tohoto pravidla je bezpečné potlačit, pokud:
- Typ označený příznakem neodpovídá za uvolnění prostředku uchovávaného polem (to znamená, že typ nemá likvidní vlastnictví).
- Volání, ke kterému Dispose dochází na hlubší úrovni volání, než kontroluje pravidlo
- vlastnictví pole nedržuje typ obsahujícího.
Potlačení upozornění
Pokud chcete pouze potlačit jedno porušení, přidejte do zdrojového souboru direktivy preprocesoru, abyste pravidlo zakázali a znovu povolili.
#pragma warning disable CA2213
// The code that's violating the rule is on this line.
#pragma warning restore CA2213
Pokud chcete pravidlo pro soubor, složku nebo projekt zakázat, nastavte jeho závažnost v none
konfiguračním souboru.
[*.{cs,vb}]
dotnet_diagnostic.CA2213.severity = none
Další informace naleznete v tématu Jak potlačit upozornění analýzy kódu.
Příklad
Následující fragment kódu ukazuje typ TypeA
, který implementuje 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);
}
}
Následující fragment kódu ukazuje typ TypeB
, který porušuje pravidlo CA2213 tím, že deklaruje pole aFieldOfADisposableType
jako uvolnitelný typ (TypeA
) a nevolá Dispose na toto pole.
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);
}
}
Chcete-li opravit porušení, zavolejte Dispose()
na uvolnitelné pole:
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);
}
}
}