代码之家  ›  专栏  ›  技术社区  ›  Robert Oschler Rob

哪些C#类对象获取非托管资源?有清单吗?

  •  2
  • Robert Oschler Rob  · 技术社区  · 11 年前

    我正在使用XML对类对象进行序列化和反序列化,这时我看到了这篇博客文章,它展示了如何在WindowsPhone7上使用隔离存储区来实现这一点。Windows Phone 7是我正在开发的平台:

    在里面 this example ,是他唯一明确调用的对象 处置() on是TextReader对象。我在MSDN上查找了TextReader对象,发现 the documentation 这样说:

    释放TextReader使用的非托管资源,也可以选择释放托管资源。

    所以我认为他这样做的原因是为了立即释放TextReader对象获取的非托管资源。如果不是因为他的博客文章,我不会想到会这么做。显然,我不想开始对看到的每一个对象调用Dispose(),那么,对于研究特定对象何时应该调用Dispose),有什么好的经验法则呢?是否有一些指南或列表,至少是需要这种特殊处理的流行.NET对象?

    4 回复  |  直到 11 年前
        1
  •  5
  •   SLaks    11 年前

    显然,我不想开始对中的每个对象调用Dispose()

    错误的

    通常,任何实现 IDisposable 应该在完成后立即处理,通常使用 using 陈述

    大多数没有非托管资源的对象不会实现 I可分发 (并且没有 Dispose() 方法),所以您无需担心。

    唯一的例外是实现的基类 I可分发 在一些派生实现具有要处理的东西的情况下(例如, IEnumerator , Component TextReader ).
    然而,需要处理哪些具体实现并不总是显而易见的(而且可能随时更改),所以无论如何都应该处理它们。

        2
  •  3
  •   Cody Gray    11 年前

    显然,我不想开始对看到的每一个对象调用Dispose(),那么,对于研究特定对象何时应该调用Dispose),有什么好的经验法则呢?

    这不是问题。编译器不允许您对未实现它的对象调用Dispose()。

    你呢 应该是 为每个对象调用Dispose() 实现它(它将通过 IDisposable 接口)。这是你应该遵循的准则。事实上,就是这样 方法 当对象实现时 I可分发 :它有需要释放的非托管资源。

    如果简单地将对象的创建和使用包装在 using 语句,例如:

    using (DisposableObject obj = new DisposableObject(...))
    {
        obj.DoWork();
    } // obj.Dispose() is automatically called here, even if an exception is thrown
    
        3
  •  2
  •   Robert Oschler Rob    11 年前

    实际上,您必须处理实现IDisposable的对象。

    与直接调用Dispose()相反,执行此操作的标准方法是:

    using(AnyIDisposable obj = ...)
    {
        // work with obj here
    }
    //The Dispose() method is already called here
    
        4
  •  0
  •   Community CDub    4 年前

    如果我错了,请纠正我。 据我所知,.NET Framework的所有类都是托管的(在程序员看来,尽管使用不足,但它们可能会使用非托管代码),所以理论上你不需要调用Dispose()或using,因为gc会注意这一点。但有时非常建议使用它们,请参阅 IDisposable Interface Which managed classes in .NET Framework allocate (or use) unmanaged memory? http://blogs.msdn.com/b/kimhamil/archive/2008/11/05/when-to-call-dispose.aspx

    编辑:(你是对的,noob)为了澄清,我将添加来自 IDisposable接口

    建议在以下情况下调用dispose或using:

    1.你的类有很多对象,并且有很多交叉引用。即使其全部得到管理,GC也可能无法回收 由于活动引用而导致的内存。你有机会(除了 编写终结器)来解开引用并断开链接 你连接它们的方式。因此,您正在帮助GC回收 内存。

    2.你打开了一些流,这些流在类的对象死之前都是活动的。即使这样的文件/网络等的实现 经过管理,它们深入到Win32模式下的句柄。因此,你得到了 有机会编写一个Dispose方法,在那里可以关闭流。这个 GDI对象也是如此,甚至更多。

    3.您正在编写一个使用非托管资源的类,并且希望将程序集发送给第三方。你最好用一次性的 模式,以确保能够释放手柄以避免 泄漏量

    4.您的类实现了许多事件处理程序,并将它们与事件挂钩。类的对象 暴露事件,如Form等,GC不会释放,因为 您的类的本地实现(可能)仍然挂接到 这些事件。您可以在Dispose中取消挂起这些事件处理程序;再一次 帮助GC。