【问题标题】:Nulling Out Managed Resources on Dispose [duplicate]在 Dispose 时清空托管资源 [重复]
【发布时间】:2023-03-26 13:02:01
【问题描述】:

可能重复:
Any sense to set obj = null(Nothing) in Dispose()?

我了解此问题是否因重复而关闭,但我在协调有关此主题的一些帖子时遇到了一些麻烦。

首先是一点背景。我有一个类 Foo 如下

public class Foo : IDisposable
{
    private Dictionary<int, string> _reallyBigDictionary = 
            new Dictionary<int, string>();

    public void Dispose()
    {
        _reallyBigDictionary = null;
    }
}

众所周知,Foo 的实例范围有限(即我知道我们不会永远保留它)。鉴于它的实例范围有限,我看不出将 _reallyBigDictionary 清零实际上比处置更快地释放内存。按照我的理解,这些对象在垃圾收集运行之前永远不会被清理。那时,对给定 Foo 实例的引用无论如何都将为空,所以我希望 GC 无论如何都会回收该内存。

这些帖子让我相信将成员变量设置为 null 是没有意义的:

Memory leak problems: dispose or not to dispose managed resources?

Is it better to destroy all objects or just let the garbage collector do the job?

这篇文章让我质疑: Proper use of the IDisposable interface

谁能为我澄清这一点?这里真的需要 IDisposable 实现吗?因为我无法说服自己确实如此。

【问题讨论】:

  • “正确使用链接”有一个很长的模糊答案,“任何意义”链接是你应该阅读的。摘要:这样做没有意义。

标签: c# .net garbage-collection idisposable


【解决方案1】:

你不需要IDisposable; here's why。总之,你需要遵循规则 1:除非你需要,否则不要实现IDisposable

只有两种情况IDisposable确实需要实现:

  • 该类拥有非托管资源。
  • 该类拥有托管 (IDisposable) 资源。

由于Dictionary&lt;int, string&gt; 不是IDisposable,你的班级也不应该是。

【讨论】:

    【解决方案2】:

    通过实现IDisposable 接口,您可以使用Using 语句来确定资源的使用范围。 底层 .NET Framework 中的许多类也检测到一个类是 IDisposable 并为您运行 Dispose(),免除您将托管子对象清空的责任。

    编辑----

    由于 cmets 和降价,我认为应该添加到我的答案中:

    .NET Framework 中的许多类都实现了 IDisposable - 例如许多通用集合类型。当您处置此类集合时,Microsoft 实现将调用您的类的 Dispose 方法,并检测到它实现了 IDisposable。此外,还有一种情况是通常将对对象的引用设置为 null - 可能包括在您的 Dispose 方法中。如果要删除对对象的引用,请将引用设置为 null。其他类可能希望维护对同一对象的引用,因此设置对 null 的引用是错误的论点是一个有缺陷的论点。使用您的 Dispose 方法将引用设置为 null 与以任何其他方式将其设置为 null 没有什么不同 - 授予,但是通过在您的 IDisposable 实现中执行此操作,您可以有一种更具确定性和防错性的方式来确保发生这种情况.实施 IDisposable 也是实施范围界定的绝佳方式,例如用于事务算法等。实现 IDisposable 在许多方面都很有用,无需避免,只要您知道它的工作原理和原因。令我惊讶的是,很少有 .NET 开发人员真正了解 IDisposable 接口、终结器、垃圾收集器和 .NET 最佳实践

    【讨论】:

    • 您是否有任何“底层 .NET 框架中的类”示例“检测到一个类是 IDisposable 并为您运行 Dispose”?
    • 当不再需要父对象时,将子对象的引用设置为 null 是不必要的,并且不会帮助释放相关的内存。不要这样做,也不要为此目的实现 IDisposable。
    • “当您处理此类集合时,Microsoft 实现将调用您的类的 Dispose 方法,检测到它实现了 IDisposable。”您有这种集合类型的特定示例吗? (不是我的反对票,fwiw。)
    • SortedDictionary 就是一个例子(有很多)
    • @Dean:你能详细说明一下吗?你所说的对我没有任何意义:SortedDictionary&lt;K,V&gt; 本身并没有实现IDisposable,而且我从来没有看到任何证据表明它“调用[ing]你的类的 Dispose 方法,检测到它实现IDisposable"。
    【解决方案3】:

    我认为在这种情况下没有必要进行处置。这不像是一个会保持打开状态并继续消耗资源的活动连接。当您使用完毕后,它会自行管理。

    如果你真的想确保这段代码没有内存泄漏,你可以尝试在 dispose 方法中添加以下内容:

    GC.Collect();
    

    【讨论】:

    • 不提倡使用,只是把它放在那里。正如我在回答中明确指出的,这不是需要任何特殊处理技术的情况。
    猜你喜欢
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 2011-12-20
    • 2011-01-18
    • 2020-02-15
    • 2019-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多