CA1816: Call GC.SuppressFinalize correctly
TypeName |
CallGCSuppressFinalizeCorrectly |
CheckId |
CA1816 |
Category |
Microsoft. Usage |
Breaking Change |
Non Breaking |
Cause
A method that is an implementation of IDisposable.Dispose does not call GC.SuppressFinalize.
A method that is not an implementation of IDisposable.Dispose calls GC.SuppressFinalize.
A method calls GC.SuppressFinalize and passes something other than this (Me in Visual Basic).
Rule Description
The IDisposable.Dispose method lets users release resources at any time before the object becoming 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 does not call the finalizer of the object.
To prevent derived types with finalizers from having to re-implement [System.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 (Me in Visual Basic).
When to Suppress Warnings
Only suppress a warning from this rule if you are deliberating using GC.SuppressFinalize to control the lifetime of other objects. Do not suppress a warning from this rule if an implementation of Dispose does not call GC.SuppressFinalize. In this situation, failing to suppress finalization degrades performance and provide no benefits.
Example
The following example shows a method that incorrectly calls GC.SuppressFinalize.
Imports System
Imports System.Data.SqlClient
Namespace Samples
Public Class DatabaseConnector
Implements IDisposable
Private _Connection As New SqlConnection
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(True) ' Violates rules
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If _Connection IsNot Nothing Then
_Connection.Dispose()
_Connection = Nothing
End If
End If
End Sub
End Class
End Namespace
using System;
using System.Data.SqlClient;
namespace Samples
{
public class DatabaseConnector : IDisposable
{
private SqlConnection _Connection = new SqlConnection();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true); // Violates rule
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_Connection != null)
{
_Connection.Dispose();
_Connection = null;
}
}
}
}
}
The following example shows a method that correctly calls GC.SuppressFinalize.
Imports System
Imports System.Data.SqlClient
Namespace Samples
Public Class DatabaseConnector
Implements IDisposable
Private _Connection As New SqlConnection
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 _Connection IsNot Nothing Then
_Connection.Dispose()
_Connection = Nothing
End If
End If
End Sub
End Class
End Namespace
using System;
using System.Data.SqlClient;
namespace Samples
{
public class DatabaseConnector : IDisposable
{
private SqlConnection _Connection = new SqlConnection();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_Connection != null)
{
_Connection.Dispose();
_Connection = null;
}
}
}
}
}
Related Rules
CA2215: Dispose methods should call base class dispose
CA2216: Disposable types should declare finalizer
See Also
Reference
Implementing Finalize and Dispose to Clean Up Unmanaged Resources