Condividi tramite


CA2202: Non eliminare oggetti più volte

TypeName

DoNotDisposeObjectsMultipleTimes

CheckId

CA2202

Category

Microsoft.Usage

Breaking Change

Non sostanziale

Causa

Un'implementazione di metodo contiene percorsi del codice che potrebbero causare più chiamate a IDisposable.Dispose o a un equivalente di Dispose, ad esempio un metodo Close() su alcuni tipi, sullo stesso oggetto.

Descrizione della regola

Un metodo Dispose implementato correttamente può essere chiamato più volte senza generare un'eccezione. Tuttavia, questo esito non è garantito e per evitare di generare un'eccezione System.ObjectDisposedException, è necessario evitare di chiamare Dispose più volte su un oggetto.

Regole correlate

CA2000: Eliminare gli oggetti prima di perdere l'ambito

Come correggere le violazioni

Per correggere una violazione di questa regola, modificare l'implementazione in modo che, a prescindere dal percorso del codice, Dispose venga chiamato una sola volta per oggetto.

Esclusione di avvisi

Non escludere un avviso da questa regola. Anche se è noto che il metodo Dispose può essere chiamato più volte senza rischi, in futuro l'implementazione potrebbe cambiare.

Esempio

Istruzioni using annidate (Using in Visual Basic) possono provocare violazioni dell'avviso CA2202. Se la risorsa IDisposable dell'istruzione using interna annidata contiene la risorsa dell'istruzione using esterna, il metodo Dispose della risorsa annidata rilascia la risorsa contenuta. Quando si verifica questa situazione, il metodo Dispose dell'istruzione using esterna tenta di eliminare la propria risorsa per una seconda volta.

Nell'esempio seguente, un oggetto Stream creato in un'istruzione using esterna viene rilasciato alla fine dell'istruzione using interna nel metodo Dispose dell'oggetto StreamWriter che contiene l'oggetto stream. Alla fine dell'istruzione using esterna, l'oggetto stream viene rilasciato una seconda volta. La seconda versione è una violazione di CA2202.

using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
    using (StreamWriter writer = new StreamWriter(stream))
    {
        // Use the writer object...
    }
}

Per risolvere questo problema utilizzare un blocco try/finally anziché l'istruzione using esterna. Nel blocco finally, verificare che la risorsa stream non sia null.

Stream stream = null;
try
{
    stream = new FileStream("file.txt", FileMode.OpenOrCreate);
    using (StreamWriter writer = new StreamWriter(stream))
    {
        stream = null;
        // Use the writer object...
    }
}
finally
{
    if(stream != null)
        stream.Dispose();
}

Vedere anche

Riferimenti

System.IDisposable

Implementazione dei metodi Finalize e Dispose per la pulizia delle risorse non gestite