Cause
Violations of this rule can be caused by:
In an unsealed class, a method that's an implementation of System.IDisposable.Dispose and doesn't call System.GC.SuppressFinalize.
A method that's not an implementation of System.IDisposable.Dispose and calls System.GC.SuppressFinalize.
A method that calls System.GC.SuppressFinalize and passes something other than this (C#) or Me (Visual Basic).
Rule description
The System.IDisposable.Dispose method lets users release resources at any time before the object becomes available for garbage collection. If the System.IDisposable.Dispose method is called, it frees resources of the object. This makes finalization unnecessary. System.IDisposable.Dispose should call System.GC.SuppressFinalize so the garbage collector doesn't call the finalizer of the object.
To prevent derived types with finalizers from having to reimplement System.IDisposable and to call it, unsealed types without finalizers should still call System.GC.SuppressFinalize.
How to fix violations
To fix a violation of this rule:
If the method is an implementation of System.IDisposable.Dispose, add a call to System.GC.SuppressFinalize.
If the method is not an implementation of System.IDisposable.Dispose, either remove the call to System.GC.SuppressFinalize or move it to the type's System.IDisposable.Dispose implementation.
Change all calls to System.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 System.GC.SuppressFinalize to control the lifetime of other objects. Don't suppress a warning from this rule if an implementation of System.IDisposable.Dispose doesn't call System.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 CA1816To disable the rule for a file, folder, or project, set its severity to none in the configuration file.
[*.{cs,vb}]
dotnet_diagnostic.CA1816.severity = noneFor more information, see How to suppress code analysis warnings.
Example that violates CA1816
This code shows a method that calls System.GC.SuppressFinalize, but doesn't pass this (C#) or Me (Visual Basic). As a result, this code violates rule CA1816.
sample · vbdocs/fundamentals/code-analysis/quality-rules/snippets/vb/all-rules/ca1816-call-gc-suppressfinalize-correctly_1.vbsnippet1
Imports System.IO
Namespace ca1816
'<snippet1>
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
'</snippet1>
End Namespace
Namespace ca1816_2
'<snippet2>
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
'</snippet2>
End Namespacesample · csharpdocs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1816.cssnippet1
using System;
using System.IO;
namespace ca1816
{
//<snippet1>
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;
}
}
}
//</snippet1>
}
namespace ca1816_2
{
//<snippet2>
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;
}
}
}
//</snippet2>
}Example that satisfies CA1816
This example shows a method that correctly calls System.GC.SuppressFinalize by passing this (C#) or Me (Visual Basic).
sample · vbdocs/fundamentals/code-analysis/quality-rules/snippets/vb/all-rules/ca1816-call-gc-suppressfinalize-correctly_1.vbsnippet2
Imports System.IO
Namespace ca1816
'<snippet1>
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
'</snippet1>
End Namespace
Namespace ca1816_2
'<snippet2>
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
'</snippet2>
End Namespacesample · csharpdocs/fundamentals/code-analysis/quality-rules/snippets/csharp/all-rules/ca1816.cssnippet2
using System;
using System.IO;
namespace ca1816
{
//<snippet1>
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;
}
}
}
//</snippet1>
}
namespace ca1816_2
{
//<snippet2>
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;
}
}
}
//</snippet2>
}Related rules
- CA2215: Dispose methods should call base class dispose
- CA2216: Disposable types should declare finalizer