Dispose和在C#中设置null引用有什么区别?

时间:2011-06-29 10:02:57

标签: c#

我有两个代码示例,我想知道它们之间有什么区别,哪个更好地用作最佳实践和性能:

using (TestForm test = new TestForm())
{
test.ShowDialog();
}

另一个是:

TestForm test = null; 
try
{
test = new TestForm();
 test.ShowDialog();
}
catch(Exception ex)
{
}
finally
{
test = null; 
}

3 个答案:

答案 0 :(得分:7)

IDisposable接口定义Dispose方法,以及使用“using”语法的可能性。可以实现类的dispose方法来释放资源,关闭数据库连接以及任何类型的最终化和清理。只是将类实例设置为null将不会执行dispose方法中定义的任何代码。作为一般规则,如果一个类实现了IDisposable,那么当你完成类实例时应该调用dispose。

答案 1 :(得分:4)

Dispose()用于释放非托管资源。这个也可以在终结器中完成(可能会调用Dispose()),但不要依赖它。如果没有完成,则泄漏非托管资源。

设置对null的引用仅表示特定引用不再指向该对象。它可以在那之后存在很长一段时间(如果你有另一个引用,甚至可以无限期地存在 - 好吧,如果你有多个对Dispose() d的对象的引用,那么它可能会很难看。

通常,当您完成Dispose()时,请始终致电IDiposable。如果将它们包装成using语句,则更容易:

using (var foo = new SomeDiposableObject()) {
  // do something with foo
}

答案 2 :(得分:-1)

IDisposable模式是一种及时释放对象可能正在消耗的非托管和托管资源的机制。

模式的典型实现方式如下:

public void Dispose() //Implementes the IDisposable interface
{ 
    this.Dispose(true);
    GC.SupressFinalize(this); //All resources have been released, no need to run the finalizer. We make the GC's life a little easier;
} 

protected void Dispose(bool disposing)
{
     if (disposing)
     {
        //Relesase managed resources.
     }

    //Release unmanaged resources.
}

~MyDisposableObject()  //finalizer
{
    this.Dispose(false)
}

这里要注意的是,通过Dispose方法释放资源与您在终结器中逻辑上预期的非常相似。由于两个主要原因,它不是直接在终结器中完成的:

  1. 终结器未按确定的顺序执行。这就是我们不从终结器Dispose(false))处置托管资源的原因,因为对象持有的部分或全部托管资源可能已在对象本身之前完成。对于非托管资源,情况并非如此,因为根据定义,它们永远不会被GC最终确定。

  2. 我们不知道何时运行终结器(它取决于GC)。

  3. 基本思想是实现IDisposable的对象是任何消费者都说的标志:“嘿,我正在坚持一定数量的非托管和/或托管资源,最终会当GC决定我不再有用时发布,但如果你需要及时回复这些资源,请调用Dispose(),我很乐意帮忙。“。

    另一方面,将引用变量设置为null并不会释放任何资源。 如果您从对象中删除的引用是该对象的唯一引用,则该对象最终将由GC收集,并且托管和非托管资源将被释放(何时,是任何人猜)。

    如果有更多的实时引用仍然指向该对象,那么该对象将存在一个,并且不会释放任何资源。