CA1816:正确调用 GC.SuppressFinalize
属性 | 值 |
---|---|
规则 ID | CA1816 |
标题 | 正确调用 GC.SuppressFinalize |
类别 | 使用情况 |
修复是中断修复还是非中断修复 | 非中断 |
在 .NET 8 中默认启用 | 作为建议 |
原因
此规则的冲突可能由以下原因引起:
在非密封类中,它是一种实现 IDisposable.Dispose 但不调用 GC.SuppressFinalize 的方法。
一种方法,不是 IDisposable.Dispose 的实现,但调用 GC.SuppressFinalize。
一种方法,调用 GC.SuppressFinalize 并传递 this (C#) 或 Me (Visual Basic) 以外的内容。
规则说明
使用 IDisposable.Dispose 方法,用户可在对象用于垃圾回收之前随时释放资源。 如果调用 IDisposable.Dispose 方法,则会释放对象的资源。 这使终止变得没有必要。 IDisposable.Dispose 应该调用 GC.SuppressFinalize,这样垃圾回收器就不会调用对象的终结器。
若要阻止带有终结器的派生类型重新实现 IDisposable 并对其进行调用,则没有终结器的未密封类型仍然应该调用 GC.SuppressFinalize。
如何解决冲突
若有解决此规则的冲突:
如果方法是 Dispose 的实现,则添加对 GC.SuppressFinalize 的调用。
如果方法不是 Dispose 的实现,请删除对 GC.SuppressFinalize 的调用或将其移动到类型的 Dispose 实现。
将所有调用更改为 GC.SuppressFinalize,以传递 this (C#) 或 Me (Visual Basic)。
如果类型不是要重写的,请将其标记为
sealed
。
何时禁止显示警告
只有在故意使用 GC.SuppressFinalize 来控制其他对象的生存期时,才禁止显示此规则发出的警告。 如果 Dispose 的实现没有调用 GC.SuppressFinalize,则不要禁止显示此规则发出的警告。 在此情况下,未能禁止显示终结会降低性能,且没有任何好处。
抑制警告
如果只想抑制单个冲突,请将预处理器指令添加到源文件以禁用该规则,然后重新启用该规则。
#pragma warning disable CA1816
// The code that's violating the rule is on this line.
#pragma warning restore CA1816
若要对文件、文件夹或项目禁用该规则,请在配置文件中将其严重性设置为 none
。
[*.{cs,vb}]
dotnet_diagnostic.CA1816.severity = none
有关详细信息,请参阅如何禁止显示代码分析警告。
与 CA1816 冲突的示例
这代码演示了一种方法,该方法调用 GC.SuppressFinalize,但不传递 this (C#) 或 Me (Visual Basic)。 结果,此代码与规则 CA1816 冲突。
Public Class DatabaseConnector
Implements IDisposable
Private _Connection As New SqlConnection
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
' Violates rules
GC.SuppressFinalize(True)
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
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;
}
}
}
}
满足 CA1816 的示例
本示例演示了一种方法,该方法通过传递 this (C#) 或 Me (Visual Basic) 来正确调用 GC.SuppressFinalize。
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
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;
}
}
}
}