Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
| Property | Value |
|---|---|
| Rule ID | CA1816 |
| Title | Call GC.SuppressFinalize correctly |
| Category | Usage |
| Fix is breaking or non-breaking | Non-breaking |
| Enabled by default in .NET 9 | As suggestion |
Cause
Violations of this rule can be caused by:
In an unsealed class, a method that's an implementation of IDisposable.Dispose and doesn't call GC.SuppressFinalize.
A method that's not an implementation of IDisposable.Dispose and calls GC.SuppressFinalize.
A method that calls GC.SuppressFinalize and passes something other than this (C#) or Me (Visual Basic).
Rule description
The IDisposable.Dispose method lets users release resources at any time before the object becomes available for garbage collection. If the IDisposable.Dispose method is called, it frees resources of the object. This makes finalization unnecessary. IDisposable.Dispose should call GC.SuppressFinalize so the garbage collector doesn't call the finalizer of the object.
To prevent derived types with finalizers from having to reimplement IDisposable and to call it, unsealed types without finalizers should still call GC.SuppressFinalize.
How to fix violations
To fix a violation of this rule:
If the method is an implementation of Dispose, add a call to GC.SuppressFinalize.
If the method is not an implementation of Dispose, either remove the call to GC.SuppressFinalize or move it to the type's Dispose implementation.
Change all calls to GC.SuppressFinalize to pass this (C#) or Me (Visual Basic).
If the type is not meant to be overridden, mark it as
sealed.
When to suppress warnings
Only suppress a warning from this rule if you're deliberately using GC.SuppressFinalize to control the lifetime of other objects. Don't suppress a warning from this rule if an implementation of Dispose doesn't call GC.SuppressFinalize. In this situation, failing to suppress finalization degrades performance and provides no benefits.
Suppress a warning
If you just want to suppress a single violation, add preprocessor directives to your source file to disable and then re-enable the rule.
#pragma warning disable CA1816
// The code that's violating the rule is on this line.
#pragma warning restore CA1816
To disable the rule for a file, folder, or project, set its severity to none in the configuration file.
[*.{cs,vb}]
dotnet_diagnostic.CA1816.severity = none
For more information, see How to suppress code analysis warnings.
Example that violates CA1816
This code shows a method that calls GC.SuppressFinalize, but doesn't pass this (C#) or Me (Visual Basic). As a result, this code violates rule CA1816.
Public Class MyStreamClass
Implements IDisposable
Private _stream As New MemoryStream
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
' Violates rule.
GC.SuppressFinalize(True)
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If _stream IsNot Nothing Then
_stream.Dispose()
_stream = Nothing
End If
End If
End Sub
End Class
public class MyStreamClass : IDisposable
{
private MemoryStream? _stream = new();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true); // Violates rule
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_stream?.Dispose();
_stream = null;
}
}
}
Example that satisfies CA1816
This example shows a method that correctly calls GC.SuppressFinalize by passing this (C#) or Me (Visual Basic).
Public Class MyStreamClass
Implements IDisposable
Private _stream As New MemoryStream
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If _stream IsNot Nothing Then
_stream.Dispose()
_stream = Nothing
End If
End If
End Sub
End Class
public class MyStreamClass : IDisposable
{
private MemoryStream? _stream = new();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_stream?.Dispose();
_stream = null;
}
}
}
Related rules
- CA2215: Dispose methods should call base class dispose
- CA2216: Disposable types should declare finalizer