关于c#:在Dispose上删除托管资源

Nulling Out Managed Resources on Dispose

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Any sense to set obj = null(Nothing) in Dispose()?

我知道这个问题是否以副本的形式结束,但我在协调关于这个主题的一些帖子时遇到了一些困难。

首先是一些背景。我有一个如下的foo班

1
2
3
4
5
6
7
8
9
10
public class Foo : IDisposable
{
    private Dictionary<int, string> _reallyBigDictionary =
            new Dictionary<int, string>();

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

已知foo的实例范围有限(即,我知道我们不会永远保留它)。考虑到它的实例范围有限,我不知道如何使空字典比释放内存更快地释放内存。据我所知,在运行垃圾收集之前,这些对象永远不会被清除。此时,对foo的给定实例的引用将为空(无论如何),因此我希望gc无论如何都能回收该内存。

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

内存泄漏问题:是否处置托管资源?

最好是销毁所有对象还是让垃圾收集器来完成这项工作?

这篇文章让我提出了另外一个问题:正确使用IDisposable接口

有人能为我澄清这一点吗?这里是否确实需要IDisposable实现?因为我就是不能说服自己。


你不需要IDisposable,这就是为什么。总之,您需要遵循规则1:除非需要,否则不要实现IDisposable

只有两种情况需要执行IDisposable

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

由于Dictionary不是IDisposable,所以您的班级也不应该是IDisposable


通过实现IDisposable接口,您可以使用Using语句来确定资源的使用范围。此外,underying.NET框架中的许多类检测到类是可IDisposable的,并为您运行Dispose(),从而免除了您取消托管子对象的责任。

编辑----

由于评论和降价,我认为我的答案中增加了:

.NET框架中的许多类实现了IDisposable,例如许多泛型集合类型。处理此类集合时,Microsoft实现将调用类的Dispose方法,检测到该方法实现了IDisposable。另外,还有一种情况是将对对象的引用设置为空genrally,这可能包括在Dispose方法中。如果要删除对对象的引用,请将该引用设置为空。其他类可能希望维护对同一对象的引用,因此将引用设置为空的参数"是错误的"是一个有缺陷的参数。使用Dispose方法将引用设置为空与以任何其他方式将其设置为空没有什么不同,但通过在IDisposable实现中进行此操作,您可以有一种更可靠和防错误的方法来确保发生这种情况。实现IDisposable也是实现范围的一种很好的方法,例如对于事务性算法等。实现IDisposable在许多方面都很有用,只要您知道它是如何工作的以及为什么工作的,就无需避免。让我惊讶的是,很少有.NET开发人员真正了解IDisposable接口、终结器、垃圾收集器和一般的.NET最佳实践。


我认为在这种情况下,处置是不必要的。它不像是一个活跃的连接,它将保持开放并不断消耗资源。当你使用完它后,它会自行管理。

如果确实要确保该代码中没有内存泄漏,可以尝试将以下内容添加到Dispose方法中:

1
GC.Collect();