我什么时候不应该打电话给 GC。SuppressFinalize(this) 在 Dispose?

When should I NOT call GC.SuppressFinalize(this) in Dispose?

提问人:Luke Vo 提问时间:11/14/2023 更新时间:11/14/2023 访问量:81

问:

我有一个简单的类,它实现了,所以它被 CA1816 击中:调用 GC。正确 SuppressFinalizeIDisposable

public class A : IDisposable
{
    // ...
    int foo

    public A()
    {
        SomeObj.SomeEvent += DoSomething;
    }

    public void Dispose()
    {
        SomeObj.SomeEvent -= DoSomething;
    }
}

将 A.Dispose() 更改为调用 GC。SuppressFinalize(对象)。这将防止引入终结器的派生类型需要重新实现“IDisposable”来调用它。

现在我已经读了这个,这个和这个,但我仍然不明白这是为了什么(更多解释见下文)。所以我的问题是

  • 如果我不明白它是什么,我应该总是添加到我的方法中吗?GC.SuppressFinalize(object)Dispose

  • 我什么时候不应该这样做,而只是禁止警告?


添加更多上下文:我仍然不明白在做什么。我知道我已经释放了一些资源(示例中的事件处理程序或资源等),但是像这样的变量仍然需要清理呢?那么“这将防止引入终结器的派生类型需要重新实现”的警告部分呢?SuppressFinalizeDisposeIDisposableint foo

C# .NET 垃圾回收 终结器

评论

0赞 500 - Internal Server Error 11/14/2023
这回答了你的问题吗?我应该在什么时候使用 GC。SuppressFinalize()?
0赞 Luke Vo 11/14/2023
@500-InternalServerError我已经在我的问题中链接了那个。它什么时候回答,但我仍然不明白它的作用,所以我的问题更多地集中在什么时候不回答,以确保我没有错误地使用它。
0赞 500 - Internal Server Error 11/14/2023
所以你做到了——我已经撤回了我的接近投票。
0赞 jmcilhinney 11/14/2023
终结器清理对象。该方法通常执行相同的清理工作。如果在终结器中要完成的某些操作在方法中没有完成,则不应抑制终结器。这种情况几乎永远不会出现,因此您几乎应该始终压制终结器。我什至想不出处置后需要最终确定的场景,但我怀疑如果你遇到一个,你会知道的。DisposeDispose
3赞 Etienne de Martel 11/14/2023
我通常会禁用 CA1816,因为如果您在我的代码库中声明终结器,那就是 20 次鞭打。

答:

2赞 shingo 11/14/2023 #1

终结器或析构函数是 C++ 的遗留问题,但在 C# 中,它延长了 GC 收集对象所需的时间。

不必要的终结器(包括空终结器、仅调用基类终结器的终结器或仅调用条件发出方法的终结器)会导致不必要的性能损失。

当您使用 dispose 模式时,您可以手动释放(或通过 using 语句)资源,不再需要终结器。方法是告诉 GC 忽略目标的终结器,像常规对象一样收集它,从而提高 GC 的性能。如果不调用此方法,则会失去使用 dispose 模式的意义,因此最好始终添加它。GC.SuppressFinalize

在某种程度上,我很困惑,因为我的班上没有这样的东西,并且仍然收到警告。

是的,您的类没有终结器,但您也不能保证其子类也没有。请注意,此分析不会在密封类中报告(根据我的测试,内部/私人类也不会)。

我什么时候不应该这样做,而只是禁止警告?

它应该永远不会。如上所述,即使你不调用,通常也只会影响性能。除非你分别在 dispose 方法和终结器中释放资源,但感觉这是某种编程错误。GC.SuppressFinalize

评论

0赞 Luke Vo 11/14/2023
啊,所以我应该打电话给他们,以防子类确实有它。您能否回答我的主要担忧:是否有任何情况我不应该使用它?我想我可以从这个答案中得到的是,如果我不知道任何特殊用例,请始终添加?GC.SuppressFinalize
1赞 shingo 11/14/2023
你最好遵循处置模式,实际上 VS 可以为你生成它。
0赞 Luke Vo 11/14/2023
谢谢,我以前读过这种模式,但并不真正了解那里发生了什么。也许我以后会再试一次。