CA1063: Implementare IDisposable correttamente
Proprietà | valore |
---|---|
ID regola | CA1063 |
Title | Implementare IDisposable correttamente |
Categoria | Progettazione |
La correzione causa un'interruzione o meno | Non causa un'interruzione |
Abilitato per impostazione predefinita in .NET 9 | No |
L'interfaccia System.IDisposable non è implementata correttamente. I possibili motivi per questo includono:
- IDisposable viene riimplementato nella classe .
-
Finalize
viene nuovamente sottoposto a override. -
Dispose()
viene sottoposto a override. - Il
Dispose()
metodo non è pubblico, sealed o denominato Dispose. -
Dispose(bool)
non è protetto, virtuale o non bloccato. - Nei tipi non bloccati,
Dispose()
deve chiamareDispose(true)
. - Per i tipi non bloccati, l'implementazione
Finalize
non chiama né ilDispose(bool)
finalizzatore della classe di base.
Violazione di uno di questi criteri attiva l'avviso CA1063.
Ogni tipo non bloccato che dichiara e implementa l'interfaccia IDisposable deve fornire il proprio protected virtual void Dispose(bool)
metodo.
Dispose()
deve chiamare Dispose(true)
e il finalizzatore deve chiamare Dispose(false)
. Se si crea un tipo non bloccato che dichiara e implementa l'interfaccia IDisposable , è necessario definirlo Dispose(bool)
e chiamarlo. Per altre informazioni, vedere Pulire le risorse non gestite (guida .NET) e Implementare un metodo Dispose.
Per impostazione predefinita, questa regola esamina solo i tipi visibili esternamente, ma è configurabile.
Tutti i IDisposable tipi devono implementare correttamente il modello Dispose.
Esaminare il codice e determinare quali delle risoluzioni seguenti correggeranno questa violazione:
Rimuovere IDisposable dall'elenco di interfacce implementate dal tipo ed eseguire l'override dell'implementazione Dispose della classe di base.
Rimuovere il finalizzatore dal tipo, eseguire l'override di Dispose(bool disposing) e inserire la logica di finalizzazione nel percorso del codice in cui 'disposing' è false.
Eseguire l'override di Dispose(bool disposing) e inserire la logica dispose nel percorso del codice in cui 'disposing' è true.
Assicurarsi che Dispose() sia dichiarato come pubblico e sealed.
Rinominare il metodo dispose in Dispose e assicurarsi che sia dichiarato come pubblico e sealed.
Assicurarsi che Dispose(bool) sia dichiarato come protetto, virtuale e non bloccato.
Modificare Dispose() in modo che chiami Dispose(true), quindi chiama SuppressFinalize sull'istanza dell'oggetto corrente (
this
oMe
in Visual Basic) e quindi restituisce .Modificare il finalizzatore in modo che chiami Dispose(false) e quindi restituisca.
Se si crea un tipo non bloccato che dichiara e implementa l'interfaccia IDisposable , assicurarsi che l'implementazione di IDisposable segua il modello descritto in precedenza in questa sezione.
Non escludere un avviso da questa regola.
Nota
Se si applicano tutti gli avvisi seguenti, è possibile che vengano visualizzati avvisi falsi positivi da questa regola:
- Si usa Visual Studio 2022 versione 17.5 o successiva con una versione precedente di .NET SDK, ovvero .NET 6 o versioni precedenti.
- Si usano gli analizzatori di .NET 6 SDK o una versione precedente dei pacchetti analizzatori, ad esempio Microsoft.CodeAnalysis.FxCopAnalyzers.
- Sono disponibili attributi per l'implementazione
IDispose
.
In questo caso, è possibile eliminare un avviso falso positivo. I falsi positivi sono dovuti a una modifica che causa un'interruzione nel compilatore C#. Prendere in considerazione l'uso di un analizzatore più recente che contiene la correzione per gli avvisi falsi positivi. Eseguire l'aggiornamento a Microsoft.CodeAnalysis.NetAnalyzers versione 7.0.0-preview1.22464.1 o successiva o usare gli analizzatori di .NET 7 SDK.
Usare l'opzione seguente per configurare le parti della codebase in cui eseguire questa regola.
È possibile configurare questa opzione solo per questa regola, per tutte le regole a cui si applica o per tutte le regole in questa categoria (Progettazione) a cui si applica. Per altre informazioni, vedere Opzioni di configurazione delle regole di qualità del codice.
È possibile configurare le parti della codebase in modo da eseguire questa regola in base alla relativa accessibilità impostando l'opzione api_surface. Ad esempio, per specificare che la regola deve essere eseguita solo sulla superficie dell'API non pubblica, aggiungere la coppia chiave-valore seguente a un file con estensione editorconfig nel progetto:
dotnet_code_quality.CAXXXX.api_surface = private, internal
Nota
Sostituire la parte XXXX
di CAXXXX
con l'ID della regola applicabile.
Lo pseudo-codice seguente fornisce un esempio generale di come Dispose(bool)
implementare in una classe che usa risorse gestite e native.
public class Resource : IDisposable
{
private bool isDisposed;
private IntPtr nativeResource = Marshal.AllocHGlobal(100);
private AnotherResource managedResource = new AnotherResource();
// Dispose() calls Dispose(true)
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// The bulk of the clean-up code is implemented in Dispose(bool)
protected virtual void Dispose(bool disposing)
{
if (isDisposed) return;
if (disposing)
{
// free managed resources
managedResource.Dispose();
}
// free native resources if there are any.
if (nativeResource != IntPtr.Zero)
{
Marshal.FreeHGlobal(nativeResource);
nativeResource = IntPtr.Zero;
}
isDisposed = true;
}
// NOTE: Leave out the finalizer altogether if this class doesn't
// own unmanaged resources, but leave the other methods
// exactly as they are.
~Resource()
{
// Finalizer calls Dispose(false)
Dispose(false);
}
}
Feedback su .NET
.NET è un progetto di open source. Selezionare un collegamento per fornire feedback: