CA2213: I campi Disposable devono essere eliminati
Proprietà | valore |
---|---|
ID regola | CA2213 |
Titolo | I campi eliminabili devono essere eliminati |
Categoria | Utilizzo |
Correzione che causa un'interruzione o un'interruzione | Nessuna interruzione |
Abilitato per impostazione predefinita in .NET 8 | No |
Causa
Tipo che implementa System.IDisposable dichiara campi di tipi che implementano IDisposableanche . Il Dispose metodo del campo non viene chiamato dal Dispose metodo del tipo dichiarante.
Descrizione regola
Un tipo è responsabile dell'eliminazione di tutte le risorse non gestite. La regola CA2213 verifica se un tipo eliminabile ,ovvero uno che implementa IDisposable, T
dichiara un campo F
che è un'istanza di un tipo FT
eliminabile . Per ogni campo F
a cui è assegnato un oggetto creato localmente all'interno dei metodi o degli inizializzatori del tipo T
contenitore , la regola tenta di individuare una chiamata a FT.Dispose
. La regola cerca i metodi chiamati da T.Dispose
e un livello inferiore , ovvero i metodi chiamati dai metodi chiamati da T.Dispose
.
Nota
Oltre ai casi speciali, la regola CA2213 viene attivata solo per i campi assegnati a un oggetto eliminabile creato localmente all'interno dei metodi e degli inizializzatori del tipo contenitore. Se l'oggetto viene creato o assegnato all'esterno del tipo T
, la regola non viene attivata. In questo modo si riduce il disturbo nei casi in cui il tipo contenitore non è responsabile dell'eliminazione dell'oggetto.
Casi speciali
La regola CA2213 può anche essere attivata per i campi dei tipi seguenti anche se l'oggetto assegnato non viene creato in locale:
Il passaggio di un oggetto di uno di questi tipi a un costruttore e quindi l'assegnazione a un campo indica un trasferimento di proprietà dispose al tipo appena costruito. Ovvero, il tipo appena costruito è ora responsabile dell'eliminazione dell'oggetto. Se l'oggetto non viene eliminato, si verifica una violazione di CA2213.
Come correggere le violazioni
Per correggere una violazione di questa regola, chiamare Dispose i campi di tipi che implementano IDisposable.
Quando eliminare gli avvisi
È possibile eliminare un avviso da questa regola se:
- Il tipo contrassegnato non è responsabile del rilascio della risorsa contenuta nel campo , ovvero il tipo non dispone della proprietà dispose.
- La chiamata a Dispose si verifica a un livello di chiamata più profondo rispetto ai controlli della regola
- la proprietà dispose dei campi non è contenuta nel tipo contenitore.
Eliminare un avviso
Se si vuole eliminare una singola violazione, aggiungere direttive del preprocessore al file di origine per disabilitare e quindi riabilitare la regola.
#pragma warning disable CA2213
// The code that's violating the rule is on this line.
#pragma warning restore CA2213
Per disabilitare la regola per un file, una cartella o un progetto, impostarne la gravità none
su nel file di configurazione.
[*.{cs,vb}]
dotnet_diagnostic.CA2213.severity = none
Per altre informazioni, vedere Come eliminare gli avvisi di analisi del codice.
Esempio
Il frammento di codice seguente mostra un tipo TypeA
che implementa 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);
}
}
Il frammento di codice seguente mostra un tipo TypeB
che viola la regola CA2213 dichiarando un campo aFieldOfADisposableType
come tipo eliminabile (TypeA
) e non chiamando Dispose sul campo.
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);
}
}
Per correggere la violazione, chiamare Dispose()
sul campo eliminabile:
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);
}
}
}