保留引用的对象会被丢弃吗?

发布于 2024-12-12 15:38:06 字数 288 浏览 2 评论 0原文

我可以知道如果“objectToBeDispose”的引用由“useDisposableObject”保留,是否会被处置?

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

May I know if the "objectToBeDisposed" will be disposed if its reference are kept by the "useDisposableObject"?

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一百个冬季 2024-12-19 15:38:06

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

顺便说一句,引用对象位于 using 块范围内,并且将在 using 块结束时超出范围,这将避免在引用对象被处置后尝试使用已处置对象时访问已处置对象的潜在问题。

感谢@dlev进行更新

Yes, in your example it will be disposed, because the using block explicitly calls the Dispose() method when leaving that block.

As an aside the referencing object is within the using block scope and will go out of scope at the end of the using block, which will avoid the potential issue of accessing a disposed object if the referencing object tried to use it once it was disposed.

Update thanks to @dlev

南风起 2024-12-19 15:38:06

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

处置只是一个“应用逻辑”的东西,它是通过处置模式来实现的。
如果实现 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)。
类中析构函数的存在会大大减慢垃圾收集器的速度,并且在析构函数内部,除了释放非托管资源之外,您几乎无法执行任何操作。

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

Disposal, finalization and memory deallocation are 3 totally different things in the .NET world.

Disposal is only an "application logic" thing, it is implemented through the disposable pattern.
If you implement the interface IDisposable, your object can be used with the using keyword.

The using keyword will translate in a simple way:

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

means

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

There is no other magic in this. That's all.

Object finalization is instead called by garbage collector when the objects should be freed.
The time when it happens and the order between destructors is unpredictable.

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

The syntax is very similar to C++ destructors but the meaning is a lot different.

And then memory deallocation.
Memory deallocation is not connected to object disposal!
You can keep forever a reference to a disposed object. Disposal is just something related to application logic.

Destructors can also be cancelled or called more than once by garbage collector (see GC.ReRegisterForFinalize and GC.SuppressFinalize).
The presence of a destructor in a class slow down a lot the garbage collector, and inside destructor, you can do almost nothing except releasing unmanaged resources.

Disposal instead as I said is an application thing, is just a method, and is not related to garbage collector.

○闲身 2024-12-19 15:38:06

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

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

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

然而,IDisposable 也有一个与之相伴的设计“契约”。此契约是实现 IDisposable 的类必须遵循的模式,才能具有正确的程序行为。

约定是,一旦调用了 Dispose(),您就不应再调用该对象的任何属性或方法,否则您应该会抛出 ObjectDisposeException。在此之后,唯一允许在该对象上调用的方法是再次调用 Dispose() 或对象终结器(通过垃圾回收)。

因此,人们有时会在处置后将 IDisposable 类的引用设置为 null,这样他们就不会意外地调用已处置对象上的方法。如果您将引用放置在 using 块中,则不必担心这一点;编译器甚至不会让你再次接触引用。如果您尝试,您将收到错误并且您的程序将无法编译。

该契约没有内置于语言或 CLR 本身中 - 它必须由类的实现者手动遵守。

"Disposing" an object has nothing to do with which references are kept around. IDisposable itself is just an interface, nothing more.

When a class implements that interface, a user of the class can call a public void Dispose() method on the object. When the user of the class places an instance of the class in a using block, the Dispose() method will automatically get called. When an Enumerator class implements IDisposable and is used in a foreach loop, it will also have Dispose() called on it.

This has absolutely nothing to do with which references are kept around, or the automatic garbage collection system.

However, IDisposable also has a design "contract" that goes with it. This contract is a pattern that classes that implement IDisposable must follow to have correct program behavior.

The contract is that once you've called Dispose(), you should never call any property or method on the object again, otherwise you should expect an ObjectDisposedException to be thrown. The only thing that is allowed to be called on that object after that point is Dispose() again, or the object finalizer (via garbage collection).

Because of this, people will sometimes set an reference to an IDisposable class to null after they have disposed it, so they don't accidentally call methods on the already-disposed object. If you placed the reference in a using block, you don't have to worry about this; The compiler won't even let you touch the reference again. If you try, you will get an error and your program will fail to compile.

This contract is not built into the language or CLR itself - it must manually be adhered to by the implementer of a class.

你没皮卡萌 2024-12-19 15:38:06

是的,会的。我可能是错的,但我不认为@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 目标。

Yes, it will be. I might be wrong, but I don't think @John Weldon's explanation is not accurate though. You can only call using on an IDisposable implementing class, and when the using exits, it will call Dispose() on the object.

The part where I don't agree is the 'because the referencing object is within the using block scope and will go out of scope at the end of the using block' part. The objects declared in scope will not always be disposed of when the using exits. If you take this example

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

At the end of this code, myInstance.ItsOtherClass is not null. innerInstance has been created in the using section and won't be garbage collected since there is still a referenced. However, the object refered by myInstance.ItsWhatever has been disposed of, since it's the using target.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文