Yijinsei
Yijinsei

Reputation: 788

Will object with reference kept be disposed?

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;
}

Upvotes: 0

Views: 1124

Answers (4)

Salvatore Previti
Salvatore Previti

Reputation: 9050

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.

Upvotes: 5

Merlyn Morgan-Graham
Merlyn Morgan-Graham

Reputation: 59101

"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.

Upvotes: 3

John Weldon
John Weldon

Reputation: 40739

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

Upvotes: 7

Tipx
Tipx

Reputation: 7505

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.

Upvotes: 0

Related Questions