2010-09-06 17 views
0

我有一个实现IDisposable接口的类。澄清有关IDisposable接口的一些事情。调用Dispose后,实例(必须)是否为null?

using System; 

class A : IDisposable 
{ 
     public void Dispose() 
     { 
      Stop(); // some actions to stop internal threads 

      this = null; 
     } 
} 

为什么我不能在分配Dispose方法this = null?我知道'这个'是只读的。

例如:

A a = new A(); 
a.Run(); 
// ... 
a.Dispose(); 
// i want in this line a = null 

我想了IDisposable和Dispose方法保证A类的实例将调用Dispose后等于空()。但事实并非如此。

回答

2

只需添加到什么已经说过:

重要的是要认识到,有对象是很重要的,并且有引用(变量),和这些都是不一样的东西

当你写var a = new object();你正在做两件事情:

  1. 创建一个新的object实例。这个实例没有“名称” - 只是内存中的一个位置。就是这样。但是,只要我们有一些东西可以称呼它,我们就称它为“鲍勃”。
  2. 声明一个变量a,这引用object刚刚创建。

现在,当你写a = null;,你在做什么鲍勃。您将a更改为引用,而不是Bob,null,或换句话说,“没有对象”。因此,您不能再使用a访问“Bob”。

这是否意味着Bob不存在?不,鲍勃仍然是他的地方。

考虑这个(这基本上是the scenario Henk mentioned):现在

var a = new object(); // Again, we're calling this object Bob. 
object b = a; 

b是另一个可变,就像a。就像a,b引用鲍勃。但是,与a一样,编写b = null;对Bob没有任何帮助。它只是改变b,以便它不再指向一个对象。

这是我要去的地方。你似乎一直的印象是这样做的:

a.Dispose(); 

...好歹也是这样做:

a = null; 

...这在某种程度上相当于这样做:

Bob= null; // nowBobis no object?

但是,如果是这样的话,那么b(上图),现在将指向没有对象,即使它是从未设置为null

无论如何,从我上面的解释,希望很明显,这不是CLR的工作原理。正如Jon指出的那样,IDisposable接口实际上与正在释放的内存无关。这是关于释放共享资源。它不 - 不能 - - 从内存中删除对象,就像它做了那样,那么我们会有我上面描述的行为(引用突然变得无效)。

我知道这只是与您关于IDisposable的具体问题松散相关,但我感觉到这个问题来自对变量和对象之间关系的误解;所以我想让这种关系更清楚。

1

这是不可能的,但也没有用。

考虑b在:

A b = a; // alias 
a.Dispose(); 
// i want in this line a = null 

而且这不是一个真正的问题,但仍然是一个对象,ab参考。它只是将其内部状态更改为“关闭”。有些IDisposable的类有一个bool IsDisposed成员,你可以安全地调用后Dispose()

+0

这不是一个问题,如果b将为空... – nik 2010-09-06 07:16:58

+0

@nik:被处置和被作为null'没有像你想象的那样密切相关 – 2010-09-06 10:29:36

3

没有,Dispose就像任何其他方法的方法尽可能的CLR而言。 C#通过using语句(和foreach以及迭代器被处置)支持它,但除此之外它没有意义。特别是,它不直接与垃圾收集器交互,或者影响任何涉及处理对象的变量。 (IDisposable的某些实现也可能有终结器,它们调用Dispose,但它们在逻辑上是截然不同的概念。)

请注意,对象在处置后不一定无法使用。例如,处理一个MemoryStream不会清除内存中的数据 - 使用ToArray之后它仍然可以工作。

事实上,the documentation for IDisposable明确地谈论它的可能性被用于复位对象重用:

使用此方法来关闭或释放非托管资源,如文件,流,并通过举办 手柄实现此接口的类的实例。按照惯例, 该方法用于与释放对象所拥有的资源相关的所有任务,或者准备对象以供重用。

+0

好吧,如果我创建了:a a = new A() ;我可以跟踪用户使其为null的时刻:a = null?我希望你明白我的意思...... – nik 2010-09-06 07:14:42

+1

不,你不能检测什么时候一个对象不再被引用,.NET运行时不会引用对象。在对对象的最后引用丢失后,对象存在未定义的时间。这是设计的,如果你想清理非托管资源,你应该使用Dispose模式。那就是生活。 – 2010-09-06 07:25:15

1

你的假设是不正确的。 Dispose()不会回收实例,也不会影响参考。

这是一个实用的方法,从框架/编译器中得到一些特别的关注,它可以让您轻松地清理GC未处理的资源。除此之外,这只是一个常规方法。调用方法不应该影响参考本身。

The recommendation实施Dispose()明确规定

为了确保资源 总是适当地清理,一 Dispose方法应该是可调用 多次没有抛出 例外。

+0

如果我创建了:A a = new A();我可以跟踪用户使其为null的时刻:a = null?我希望你明白我的意思...... – nik 2010-09-06 07:15:19

+0

@nik:不,你不能那样做。 – 2010-09-06 07:35:23

相关问题