我有一个实现IDisposable接口的类。
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方法保证在调用Dispose()之后,类A的实例将等于null。但事实并非如此。
答案 0 :(得分:3)
不,就{CL}而言,Dispose
只是一种方法,就像任何其他方法一样。 C#通过using
语句支持它(并且foreach
并且迭代器被释放),但除此之外没有任何意义。特别是,它不直接与垃圾收集器交互,或影响引用已处置对象的任何变量。 (IDisposable
的某些实现也可能具有调用Dispose
的终结器,但它们在逻辑上是不同的概念。)
请注意,对象在处理后不一定无法使用。例如,处置MemoryStream
并不会清除内存中的数据 - 之后使用ToArray
仍可以使用。
确实,the documentation for IDisposable
明确地谈到了它被用于重置对象以供重用的可能性:
使用此方法关闭或释放非托管资源,例如文件,流和 由实现此接口的类的实例持有的句柄。按照惯例, 此方法用于与释放对象持有的资源相关的所有任务,或 准备重新使用的对象。
答案 1 :(得分:2)
只是添加到已经说过的内容:
重要的是要意识到有对象,并且有引用(变量),而这些不是同一个东西。< / p>
当你写var a = new object();
时,你正在做两件事:
object
实例。此实例没有“名称” - 只是内存中的一个位置。就是这样。但是,我们有一些东西可以称之为“鲍勃。”a
,引用刚刚创建的object
。现在,当您编写a = null;
时,您正在向Bob执行 nothing 。您正在将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
引用了Bob。但同样,就像a
一样,写b = null;
对鲍勃没有任何作用。它只是更改b
,以便它不再指向对象。
这是我要去的地方。你似乎一直认为这样做:
a.Dispose();
......不知何故也这样做了:
a = null;
......这在某种程度上等同于这样做:
<强> Bob
强> = null; // now
的 Bob
强> is no object?
但如果是这种情况,那么b
(上图)现在会指向无对象,即使它从未设置为null
!< /强>
无论如何,根据我上面的解释,希望很明显这不是CLR的工作原理。正如Jon指出的那样,IDisposable
接口实际上与释放的内存无关。它是关于释放共享资源。它没有 - 不能 - 从内存中删除对象,就好像它一样,然后我们会有上面描述的行为(引用突然变得无效)。
我知道这只与你关于IDisposable
的具体问题松散地相关,但我感觉这个问题来自对变量和对象之间关系的误解;所以我想让这种关系更加清晰。
答案 2 :(得分:1)
这是不可能的,但也没有用。
在以下位置考虑b
:
A b = a; // alias
a.Dispose();
// i want in this line a = null
这不是一个真正的问题,仍然有一个a
和b
引用的对象。它只是将其内部状态更改为“已关闭”。一些IDisposable类有一个bool IsDisposed
成员,您可以在Dispose()
答案 3 :(得分:1)
您的假设不正确。 Dispose()
不会回收实例,也不会影响引用。
这是一种实用方法,它得到了框架/编译器的特别关注,可以让您轻松清理GC未处理的资源。除此之外,它只是一种常规方法。调用方法不应该影响引用本身。
The recommendation用于实施Dispose()
具体说明
帮助确保资源 总是妥善清理,a 处理方法应该是可调用的 多次而不抛弃 异常。