有引用的对象将被处理

本文关键字:处理 对象 引用 | 更新日期: 2023-09-27 18:12:54

我可以知道如果" objecttobedisposal "将被处置,如果它的引用是由"useDisposableObject"保存?

using(IDisposable objectToBeDisposed = new ObjectImplementedIDisposable  ()){
ChildObject useDisposableObject = new ChildObject(objectToBeDisposed);
.... doing stuff with useDisposableObject;
}

有引用的对象将被处理

是的,在您的示例中它将被处置,因为using块在离开该块时显式调用Dispose()方法。

作为题外话,引用对象在using块范围内,并且将在using块结束时离开作用域,这将避免如果引用对象在被处置后试图使用它,则访问已处置对象的潜在问题。

更新感谢@dlev

在。net世界中,处置、终结和内存释放是三件完全不同的事情。

处置只是一个"应用程序逻辑"的事情,它是通过disposable模式实现的。如果你实现了接口IDisposable,你的对象可以和using关键字一起使用。

using关键字将以一种简单的方式进行翻译:

using (IDisposable xxx = new MyObject())
{
    ....
}

{
    IDisposable xxx = new MyObject();
    try
    {
        ....
    }
    finally
    {
        if (xxx != null)
            xxx.Dispose();
    }
}

这里面没有别的魔法。就是这样。

当对象应该被释放时,由垃圾收集器调用对象结束。它发生的时间和析构函数之间的顺序是不可预测的。

class myclass { ~myclass() { this code will be called by garbage collector, i cannot call it } }

语法与c++析构函数非常相似,但含义有很大不同。

然后是内存回收。内存释放没有连接到对象处理!您可以永远保留对已处置对象的引用。处置只是与应用程序逻辑相关的事情。

析构函数也可以被垃圾收集器取消或多次调用(参见GC。ReRegisterForFinalize和GC.SuppressFinalize)。类中析构函数的存在大大降低了垃圾收集器的速度,并且在析构函数中,除了释放非托管资源之外,您几乎什么也做不了。

处置就像我说的是一个应用程序的事情,只是一个方法,与垃圾收集器无关

对象的"处置"与保存哪些引用无关。IDisposable本身只是一个接口,仅此而已。

当一个类实现该接口时,该类的用户可以调用对象上的public void Dispose()方法。当类的用户将类的实例放在using块中时,将自动调用Dispose()方法。当Enumerator类实现IDisposable并在foreach循环中使用时,它也将在其上调用Dispose()

这与保存哪些引用或自动垃圾收集系统完全无关。

然而,IDisposable也有一个设计"契约"。这个契约是实现IDisposable的类必须遵循的模式,以获得正确的程序行为。

约定是,一旦你调用了Dispose(),你就不应该再调用对象上的任何属性或方法,否则你应该期待一个ObjectDisposedException被抛出。在此点之后,唯一允许在该对象上调用的是Dispose(),或者对象终结器(通过垃圾收集)。

因此,人们有时会在销毁IDisposable类之后将其引用设置为null,这样他们就不会意外地在已经销毁的对象上调用方法。如果你把引用放在using块中,你不必担心这个问题;编译器甚至不会让你再碰这个引用。如果您尝试,您将得到一个错误,您的程序将无法编译。

这个契约是不是内置于语言或CLR本身的——它必须由类的实现者手动遵守。

会的。我可能错了,但我不认为@John Weldon的解释是不准确的。您只能在IDisposable实现类上调用using,并且当using退出时,它将在对象上调用Dispose()

我不同意的部分是"因为引用对象在using块范围内,并且将在using块结束时超出范围"部分。当using退出时,在作用域中声明的对象并不总是会被处理掉。如果以

为例
JustAClass myInstance = new JustAClass();
using ( MyDisposableClass theUsingInstance = new MyDisposableClass() )
{
    AnotherClass innerInstance = new AnotherClass();
    myInstance.ItsOtherClass = innerInstance;
    myInstance.ItsWhatever = theUsingInstance;
}

在代码末尾,myInstance.ItsOtherClass不是nullinnerInstance已经在using节中创建,并且不会被垃圾收集,因为仍然有一个引用。但是,myInstance.ItsWhatever引用的对象已经被处理掉了,因为它是using的目标。