C# 澄清关于IDisposable接口的一些事情。调用Dispose后实例(必须)是否等于null?
我有一个实现IDisposable接口的类C# 澄清关于IDisposable接口的一些事情。调用Dispose后实例(必须)是否等于null?,c#,.net,C#,.net,我有一个实现IDisposable接口的类 using System; class A : IDisposable { public void Dispose() { Stop(); // some actions to stop internal threads this = null; } } 为什么我不能在Dispose方法中分配this=null?我知道“this”是只读的 例如: A
using System;
class A : IDisposable
{
public void Dispose()
{
Stop(); // some actions to stop internal threads
this = null;
}
}
为什么我不能在Dispose方法中分配this=null
?我知道“this”是只读的
例如:
A a = new A();
a.Run();
// ...
a.Dispose();
// i want in this line a = null
我认为IDisposable和Dispose方法保证调用Dispose()后类A的实例将等于null。但这不是真的。这是不可能的,但也没有用处 考虑以下内容中的
b
:
A b = a; // alias
a.Dispose();
// i want in this line a = null
这并不是一个真正的问题,仍然有一个
a
和b
引用的对象。它只是将其内部状态更改为“关闭”。某些IDisposable类有一个bool IsDisposed
成员,您可以在Dispose()
否之后安全地调用该成员,Dispose
就CLR而言,与任何其他方法一样,只是一种方法。C#通过使用
语句(以及foreach
并释放迭代器)对其提供支持,但除此之外,它没有任何意义。特别是,它不会直接与垃圾收集器交互,也不会影响引用已处置对象的任何变量。(一些IDisposable
的实现可能还具有调用Dispose
的终结器,但它们在逻辑上是不同的概念。)
请注意,对象在处理后不一定不可用。例如,处理MemoryStream
不会清除内存中的数据-之后对其使用ToArray
仍将有效
实际上,本文明确讨论了使用它重置对象以供重用的可能性:
使用此方法关闭或释放非托管资源,如文件、流和文件
由实现此接口的类的实例持有的句柄。按照惯例,
此方法用于与释放对象所持有的资源相关联的所有任务,或
准备要重用的对象
你的假设是错误的
Dispose()
不会回收实例,也不会影响引用
它是一种实用方法,框架/编译器会特别关注它,它允许您轻松清理GC未处理的资源。除此之外,它只是一种常规方法。调用方法不应影响引用本身
用于实现Dispose()
特别声明
帮助确保资源得到充分利用
始终保持适当的清洁
Dispose方法应可调用
多次而不抛出
例外
只是为了补充已经说过的话: 重要的是要认识到,有对象,也有引用(变量),它们不是一回事 当您编写
var a=newobject()时代码>您正在做两件事:
创建新的对象
实例。这个实例没有“名称”——只是内存中的一个位置。事实就是这样。但是,为了让我们把它叫做“鲍勃”
声明一个变量a
,该变量引用刚刚创建的对象
现在,当你写a=null代码>,你对鲍勃什么都没做。您正在将a
更改为reference,而不是Bob、null
,或者换句话说,“无对象”。因此,您不能再使用a
访问“Bob”
这是否意味着现在鲍勃不存在了?不,鲍勃还在他原来的地方
考虑这一点(基本上是):
现在,b
是另一个变量,就像a
一样。就像a
,b
引用了Bob。但同样,就像a
一样,写入b=null代码>对鲍勃没有任何影响。它只是更改b
,使其不再指向对象
这就是我要说的。你似乎有这样的印象:
a.Dispose();
……不知何故也做到了这一点:
a = null;
…这在某种程度上等同于这样做:
a.Dispose();
Bob
=null;//现在
鲍勃
没有对象了吗?
但是如果是这样,那么b
(上面)现在将不会指向任何对象,即使它从未设置为null
强>
无论如何,从我上面的解释来看,希望很明显,CLR并不是这样工作的。正如Jon指出的,IDisposable
接口实际上与释放内存无关。它是关于释放共享资源的。它不会——不能——从内存中删除对象,就好像它删除了一样,那么我们就会有我上面描述的行为(引用突然不知从何处变得无效)
我知道这与您关于IDisposable
的具体问题关系不大,但我感觉到这个问题来自于对变量和对象之间关系的误解;所以我想让这种关系更清楚。好的,如果我创建:A A=新A();我是否可以跟踪用户将其设置为null的时刻:a=null?我希望您理解我的意思…不,您无法检测对象何时不再被引用,.NET运行时不重新计算对象。在对对象的最后一次引用丢失后,对象存在一段未定义的时间。这是出于设计考虑的,如果希望清理非托管资源,则应该使用Dispose模式。这就是生活。如果我创造了:A=新的A();我是否可以跟踪用户将其设置为null的时刻:a=null?我希望你明白我的意思…@nik:被处置和被null
没有你想象的那么紧密