Implement IDisposable correctly
Implement IDisposable correctly
Microsoft docsDescription
All System.IDisposable types should implement the Dispose pattern correctly.
Cause
The System.IDisposable interface is not implemented correctly. Possible reasons for this include:
- System.IDisposable is reimplemented in the class.
Finalizeis overridden again.Dispose()is overridden.- The
Dispose()method is not public, sealed, or named Dispose. Dispose(bool)is not protected, virtual, or unsealed.- In unsealed types,
Dispose()must callDispose(true). - For unsealed types, the
Finalizeimplementation does not call either or bothDispose(bool)or the base class finalizer.
Violation of any one of these patterns triggers warning CA1063.
Every unsealed type that declares and implements the System.IDisposable interface must provide its own protected virtual void Dispose(bool) method. Dispose() should call Dispose(true), and the finalizer should call Dispose(false). If you create an unsealed type that declares and implements the System.IDisposable interface, you must define Dispose(bool) and call it. For more information, see Clean up unmanaged resources (.NET guide) and Implement a Dispose method.
By default, this rule only looks at externally visible types, but this is configurable.
How to fix violations
Examine your code and determine which of the following resolutions will fix this violation:
- Remove System.IDisposable from the list of interfaces that are implemented by your type, and override the base class Dispose implementation instead.
- Remove the finalizer from your type, override Dispose(bool disposing), and put the finalization logic in the code path where 'disposing' is false.
- Override Dispose(bool disposing), and put the dispose logic in the code path where 'disposing' is true.
- Make sure that Dispose() is declared as public and sealed.
- Rename your dispose method to Dispose and make sure that it's declared as public and sealed.
- Make sure that Dispose(bool) is declared as protected, virtual, and unsealed.
- Modify Dispose() so that it calls Dispose(true), then calls System.GC.SuppressFinalize on the current object instance (
this, orMein Visual Basic), and then returns.
- Modify your finalizer so that it calls Dispose(false) and then returns.
- If you create an unsealed type that declares and implements the System.IDisposable interface, make sure that the implementation of System.IDisposable follows the pattern that is described earlier in this section.
Example
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);
}
}When to suppress
Do not suppress a warning from this rule. You might see false positive warnings from this rule if all of the following apply:
- You're using Visual Studio 2022 version 17.5 or later with an older version of the .NET SDK, that is, .NET 6 or earlier.
- You're using the analyzers from the .NET 6 SDK or an older version of the analyzer packages, such as Microsoft.CodeAnalysis.FxCopAnalyzers.
- You have attributes on your
IDisposeimplementation.
In this case, it's safe to suppress a false positive warning. The false positives are due to a breaking change in the C# compiler. Consider using a newer analyzer that contains the fix for the false positive warnings. Upgrade to Microsoft.CodeAnalysis.NetAnalyzers version 7.0.0-preview1.22464.1 or newer or use the analyzers from the .NET 7 SDK.