随着我对 C# 和 GC 的深入研究,我发现越来越多的事情我不太确定。我一直认为只有在我的类中有一些非托管资源时才需要 Dispose 和相应的 Finalizer。
但我有很多情况只有原生 C# 类,我不太清楚是否需要 Dispose 和相应的终结器。例如,当我将事件处理程序附加到我的事件时。
调用 Dispose 时是否需要删除事件处理程序?另外有人告诉我,如果事件处理程序仍然附加,则该对象可能不会被收集。如果是这种情况,则 GC 会以某种方式受到损害。
是否可以总结一下何时以及如何实现 Dispose 和 Finalizer?
事实上我对此有更多疑问,但也许对这个问题的回答可以帮助我进一步。
最佳答案
要弄清您关于何时进行 Dispose 和 Finalize 的一般性问题:
如果您的类(class)中有一个字段是 IntPtr
(或一些其他类型的非托管资源,但 IntPtr
是最常见的)并且您的类有责任清理该资源,然后您需要实现终结器。在该终结器中,您也应该释放 IntPtr
指向的任何资源。如果您没有 IntPtr,那么您持有的类应该处理自己的终结并实现 IDisposeable
(请参阅下一部分)
如果你的类中有一个字段实现了IDisposable
并且您的类负责在该对象之后清理您的类还应该实现 IDisposable
并且在该 dispose 方法中您应该对该对象调用 Dispose()
。
对于事件处理程序,这是个人喜好的问题。你可以,但只有你做与不做才重要if the person who subscribed to the event messed up their code .
Unless you expect the publisher of the event to outlive the subscriber, there's no reason to remove the event handler...
我个人不这样做,但我认识一些这样做的人。如果您想这样做,该过程只需在您的 dispose 方法中将事件处理程序设置为 null
。
public sealed class Example : IDisposable
{
public EventHandler MyEvent;
public void Dispose()
{
MyEvent = null;
}
}
编辑:很好的一点是Hans Passant brought up in the comments : 你永远不需要终结器,如果你有一个需要终结器的非托管资源,它应该被包裹在 SafeHandle
中。包装器为您处理最终确定。一旦你这样做了,对象就变成了另一个普通的 IDisposable
,你需要在你的 .Dispose()
方法中处理。
关于c# - 我必须删除处理程序吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29084266/