CA1816:正确调用 GC.SuppressFinalize

属性
规则 ID CA1816
标题 正确调用 GC.SuppressFinalize
类别 使用情况
修复是中断修复还是非中断修复 非中断
在 .NET 9 中默认启用 作为建议

原因

此规则的冲突可能由以下原因引起:

规则说明

使用 IDisposable.Dispose 方法,用户可在对象用于垃圾回收之前随时释放资源。 如果调用 IDisposable.Dispose 方法,则会释放对象的资源。 这使终止变得没有必要。 IDisposable.Dispose 应该调用 GC.SuppressFinalize,这样垃圾回收器就不会调用对象的终结器。

若要阻止带有终结器的派生类型重新实现 IDisposable 并对其进行调用,则没有终结器的未密封类型仍然应该调用 GC.SuppressFinalize

如何解决冲突

若有解决此规则的冲突:

何时禁止显示警告

只有在故意使用 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;
            }
        }
    }
}

另请参阅