Dispose和在C#中将引用设置为null之间有什么区别

本文关键字:之间 null 什么 区别 设置 和在 引用 Dispose | 更新日期: 2023-09-27 18:00:43

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

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

另一种是:

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

Dispose和在C#中将引用设置为null之间有什么区别

IDisposable接口定义Dispose方法,以及使用"using"语法的可能性。类的dispose方法可以实现为释放资源、关闭数据库连接以及任何类型的最终确定和清理。仅仅将类实例设置为null不会执行dispose方法中定义的任何代码。作为一般规则,如果类实现IDisposable,则应在完成类实例时调用dispose。

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

将引用设置为null仅意味着特定引用不再指向该对象。在那之后,它可能会持续很长一段时间(甚至是无限期地,如果你有另一个引用——好吧,如果你对一个Dispose()d的对象有多个引用,那么它可能会变得很难看)。

通常情况下,在IDiposable上使用完它们后,请始终调用Dispose()。如果将它们包装成using语句,则会更容易:

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

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)。

基本思想是,实现IDisposable的对象是任何消费者的一个标志:"嘿,我持有一定数量的非托管和/或托管资源,当GC决定我不再有用时,这些资源最终会被释放,但如果您需要及时返回这些资源,请调用Dispose(),我很乐意帮忙。"。

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

如果有更多的活动引用仍然指向该对象,那么该对象将是活动引用,并且不会释放任何资源。