C# 你能开一个”吗;“处置”;如果终结器调用了Dispose(),则返回事件?

C# 你能开一个”吗;“处置”;如果终结器调用了Dispose(),则返回事件?,c#,events,garbage-collection,dispose,idisposable,C#,Events,Garbage Collection,Dispose,Idisposable,我注意到MSDN()上有一些类有一个带有以下注释的Disposing事件: 在调用Dispose或垃圾收集器完成并收集此对象时发生 我想在我的类中实现我自己的处理事件。下面是我的基本实现(): 有人在我的代码审查中提到,他们不确定触发这样的事件是否安全,因为Dispose()可能会从终结器中调用,但是,根据我在顶部添加的MSDN链接上的注释,很明显,当事件被释放或终结时,会有对象触发事件 我是错过了什么还是安全了?如何实现从dispose或最终确定时触发的事件?如果答案是“不,你永远不能这样做”

我注意到MSDN()上有一些类有一个带有以下注释的
Disposing
事件:

在调用Dispose或垃圾收集器完成并收集此对象时发生

我想在我的类中实现我自己的
处理
事件。下面是我的基本实现():

有人在我的代码审查中提到,他们不确定触发这样的事件是否安全,因为Dispose()可能会从终结器中调用,但是,根据我在顶部添加的MSDN链接上的注释,很明显,当事件被释放或终结时,会有对象触发事件


我是错过了什么还是安全了?如何实现从dispose或最终确定时触发的事件?如果答案是“不,你永远不能这样做”,那么还有其他方法可以达到同样的效果吗?(正在处理或最终确定的对象的事件)

如果要在
Dispose
方法中执行任何涉及其他对象的操作,则只能在显式调用
Dispose
时执行,而不是在从最终确定器调用时执行


原因是,如果其他对象也符合收集条件,则无法保证该对象尚未最终确定。

您应该使用标准的建议实现和模式,如命名和约定,而不是自己滚动。特别是,你应该使用
bool disposing
而不是
bool from finalizer
@LasseV.Karlsen当然,我改变了名字。你可能想阅读Eric Lipperts的帖子,了解在finalizers中可能发生的所有奇怪情况。如果disposing为false,永远,永远不要引发事件。您负担不起从终结器运行任意代码,它不会导致问题的可能性非常低。Dispose事件只有在您能够保证Dispose()方法将被调用时才是合理的。除非类对象完全在您的控制之下,@HansPassant
GraphicsDevice
如何实现在释放或最终确定时可以触发的事件?它是由微软实施的;我可以想象,如果它有问题,它会被注意到。那么像我链接的
GraphicsDevice
这样的东西是如何产生一个事件的,它说“当调用Dispose或当这个对象完成时”会被触发的呢?如果我能保证订阅者的寿命比出版商长呢?你可以很容易地编写代码来做到这一点,但这样做既不推荐,也不一定安全。因此,我对微软制作的类如何实现它感到困惑。我发现很难相信XNA框架中内置的功能,如
GraphicsDevice
StorageContainer
能够做到这一点,但没有注意到这些事件在任何地方都不安全。如果答案是“不,你永远做不到”,那么还有其他方法可以达到同样的效果吗?我没说你做不到。我说你不应该。你问的是一般性问题,你会得到一般性的答案。如果您有特定的类,您可以通过这样的方式编程,即对最终确定的对象调用Dispose可以保证安全,那么就开始吧。一般的建议是不要这样做。如果你设法使终结线程崩溃,你的应用程序可能会失败。
public abstract class Handle : IDisposable
{
    public bool Disposed { get; private set; }

    public event System.Action DisposingCompleted;

    public Handle()
    {
        Disposed = false;
    }

    ~Handle()
    {
        Dispose(false);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing = false)
    {
        if (Disposed)
        {
            return;
        }

        if (disposing)
        {
            HandleManagedResources();
        }

        HandleUnManagedResources();

        Disposed = true;

        if (DisposingCompleted != null)
        {
            DisposingCompleted();
        }
    }

    protected virtual void HandleManagedResources() {}
    protected virtual void HandleUnManagedResources() {}
}