提问人:Luke Vo 提问时间:11/14/2023 更新时间:11/14/2023 访问量:81
我什么时候不应该打电话给 GC。SuppressFinalize(this) 在 Dispose?
When should I NOT call GC.SuppressFinalize(this) in Dispose?
问:
我有一个简单的类,它实现了,所以它被 CA1816 击中:调用 GC。正确 SuppressFinalize:IDisposable
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
我什么时候不应该这样做,而只是禁止警告?
添加更多上下文:我仍然不明白在做什么。我知道我已经释放了一些资源(示例中的事件处理程序或资源等),但是像这样的变量仍然需要清理呢?那么“这将防止引入终结器的派生类型需要重新实现”的警告部分呢?SuppressFinalize
Dispose
IDisposable
int foo
答:
终结器或析构函数是 C++ 的遗留问题,但在 C# 中,它延长了 GC 收集对象所需的时间。
不必要的终结器(包括空终结器、仅调用基类终结器的终结器或仅调用条件发出方法的终结器)会导致不必要的性能损失。
当您使用 dispose 模式时,您可以手动释放(或通过 using 语句)资源,不再需要终结器。方法是告诉 GC 忽略目标的终结器,像常规对象一样收集它,从而提高 GC 的性能。如果不调用此方法,则会失去使用 dispose 模式的意义,因此最好始终添加它。GC.SuppressFinalize
在某种程度上,我很困惑,因为我的班上没有这样的东西,并且仍然收到警告。
是的,您的类没有终结器,但您也不能保证其子类也没有。请注意,此分析不会在密封类中报告(根据我的测试,内部/私人类也不会)。
我什么时候不应该这样做,而只是禁止警告?
它应该永远不会。如上所述,即使你不调用,通常也只会影响性能。除非你分别在 dispose 方法和终结器中释放资源,但感觉这是某种编程错误。GC.SuppressFinalize
评论
GC.SuppressFinalize
评论
Dispose
Dispose