Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 澄清关于IDisposable接口的一些事情。调用Dispose后实例(必须)是否等于null?_C#_.net - Fatal编程技术网

C# 澄清关于IDisposable接口的一些事情。调用Dispose后实例(必须)是否等于null?

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

我有一个实现IDisposable接口的类

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
    没有你想象的那么紧密