参考对象是否会被丢弃?

时间:2011-10-31 04:01:23

标签: c# .net idisposable

如果“objectToBeDisposed”的引用由“useDisposableObject”保存,我是否可以知道它?

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

4 个答案:

答案 0 :(得分:7)

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

另外,引用对象位于using块范围内,并且将在using块的末尾超出范围,这将避免在引用对象尝试使用它之后访问已处置对象的潜在问题处置了。

感谢@dlev

答案 1 :(得分:5)

在.NET世界中,处理,终结和内存释放是完全不同的东西。

处置只是一种“应用逻辑”的东西,它是通过一次性模式实现的。 如果您实现了接口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.RegisterForFinalize和GC.SuppressFinalize)。 类中析构函数的存在会减慢垃圾收集器的速度,而在析构函数中,除了释放非托管资源之外,几乎什么都不做。

我所说的处理是一个应用程序,只是一种方法,与垃圾收集器无关。

答案 2 :(得分:3)

“处置”一个对象与哪些引用保持在一起无关。 IDisposable本身只是一个界面,仅此而已。

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

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

但是,IDisposable也有一个与之相关的设计“合同”。此契约是一种模式,实现IDisposable的类必须遵循以具有正确的程序行为。

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

因此,人们有时会在处理IDisposable类之后将null类的引用设置为using,因此它们不会意外地调用已经处置的对象上的方法。如果您将引用放在{{1}}块中,则不必担心这个问题;编译器甚至不允许您再次触摸引用。如果你尝试,你将收到一个错误,你的程序将无法编译。

此合约内置于语言或CLR本身 - 必须由类的实施者手动遵守。

答案 3 :(得分:0)

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

我不同意的部分是'因为引用对象在使用块范围内,并且将超出使用块'部分末尾的范围。当使用退出时,在范围中声明的对象不会总是被处理掉。如果你拿这个例子

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

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