正确调用 GC.SuppressFinalize
更新:2007 年 11 月
TypeName |
CallGCSuppressFinalizeCorrectly |
CheckId |
CA1816 |
类别 |
Microsoft.Usage |
是否重大更改 |
否 |
原因
作为 Dispose 的实现的方法没有调用 GC.SuppressFinalize。
- 或 -
不是 Dispose 的实现的方法调用了 GC.SuppressFinalize。
- 或 -
方法调用了 GC.SuppressFinalize 并且传递的内容不是 this(在 Visual Basic 中为 Me)。
规则说明
使用 Dispose 方法,用户可以在可将对象作为垃圾回收之前随时释放资源。如果调用了 Dispose 方法,此方法会释放对象的资源。这样,就没有必要进行终止。Dispose 应调用 GC.SuppressFinalize 以使垃圾回收器不调用对象的终结器。
若要使带有终结器的派生类型无需重新实现 [System.IDisposable] 和调用它,不带终结器的非密封类型仍然应调用 GC.SuppressFinalize。
如何修复冲突
若要修复与该规则的冲突,请执行以下操作:
如果相应方法是 Dispose 的实现,请添加对 GC.SuppressFinalize 的调用。
如果相应方法不是 Dispose 的实现,请移除对 GC.SuppressFinalize 的调用或将其移到相应类型的 Dispose 实现中。
将对 GC.SuppressFinalize 的所有调用更改为传递 this(在 Visual Basic 中为 Me)。
何时禁止显示警告
只有在您考虑使用 GC.SuppressFinalize 来控制其他对象的生存期时,才应禁止显示此规则发出的警告。如果 Dispose 的实现没有调用 GC.SuppressFinalize,请勿禁止显示此规则发出的警告。在这种情况下,如果取消终止失败,则会使性能下降且不会有任何好处。
示例
下面的示例演示一个方法,该方法向 GC.SuppressFinalize 传递了 true(在 Visual Basic 中为 true),从而对其进行了错误调用。
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;
}
}
}
}
}
下面的示例显示了一个正确调用 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;
}
}
}
}
}