Reputation: 788
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
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
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
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
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