您是否需要处理对象并将其设置为null,或者当它们超出作用域时,垃圾收集器将清理它们?


当前回答

正如其他人所说,如果类实现了IDisposable,则肯定需要调用Dispose。我在这个问题上的立场相当坚定。例如,有些人可能会声称在DataSet上调用Dispose是没有意义的,因为他们分解了DataSet,发现它没有做任何有意义的事情。但是,我认为这种说法有很多谬误。

阅读这篇文章,你会看到一场由受人尊敬的人就这个问题展开的有趣辩论。然后阅读我的推理,为什么我认为杰弗里·里希特站在错误的阵营。

现在,关于是否应该将引用设置为null。答案是否定的。让我用下面的代码来说明我的观点。

public static void Main()
{
  Object a = new Object();
  Console.WriteLine("object created");
  DoSomething(a);
  Console.WriteLine("object used");
  a = null;
  Console.WriteLine("reference set to null");
}

So when do you think the object referenced by a is eligible for collection? If you said after the call to a = null then you are wrong. If you said after the Main method completes then you are also wrong. The correct answer is that it is eligible for collection sometime during the call to DoSomething. That is right. It is eligible before the reference is set to null and perhaps even before the call to DoSomething completes. That is because the JIT compiler can recognize when object references are no longer dereferenced even if they are still rooted.

其他回答

如果它们实现了IDisposable接口,那么你应该释放它们。垃圾收集器会处理剩下的事情。

EDIT:处理一次性物品时最好使用using命令:

using(var con = new SqlConnection("..")){ ...

在c#中,你永远不需要将对象设置为空。编译器和运行时将负责找出它们何时不再在作用域中。

是的,你应该处理实现IDisposable的对象。

如果对象实现了IDisposable,那么是的,你应该释放它。对象可能挂在本地资源(文件句柄、操作系统对象)上,否则这些资源可能不会立即释放。这可能导致资源短缺、文件锁定问题和其他本来可以避免的微妙错误。

参见在MSDN上实现一个Dispose方法。

我也得回答。 JIT从对变量使用情况的静态分析中生成表和代码。 这些表项是当前堆栈帧中的“GC-Roots”。随着指令指针的前进,这些表项变得无效,因此准备进行垃圾收集。 因此:如果它是一个作用域变量,你不需要将它设置为null - GC将收集该对象。 如果它是一个成员或静态变量,则必须将其设置为null

当对象不再被使用并且垃圾回收器认为合适时,对象将被清理。有时,您可能需要将一个对象设置为null以使其超出作用域(例如您不再需要其值的静态字段),但总体而言,通常不需要将其设置为null。

关于处置对象,我同意@Andre的观点。如果对象是IDisposable的,那么在不再需要它时释放它是个好主意,特别是当对象使用非托管资源时。不处理非托管资源将导致内存泄漏。

一旦程序离开using语句的作用域,就可以使用using语句自动处理对象。

using (MyIDisposableObject obj = new MyIDisposableObject())
{
    // use the object here
} // the object is disposed here

其功能等价于:

MyIDisposableObject obj;
try
{
    obj = new MyIDisposableObject();
}
finally
{
    if (obj != null)
    {
        ((IDisposable)obj).Dispose();
    }
}