有引用的对象将被处理
本文关键字:处理 对象 引用 | 更新日期: 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
不是null
。innerInstance
已经在using节中创建,并且不会被垃圾收集,因为仍然有一个引用。但是,myInstance.ItsWhatever
引用的对象已经被处理掉了,因为它是using
的目标。