Is it legal to call a method on disposed object? If yes, why?
In the following demo program, I've a disposable class A
(which implements IDisposable
interface).As far as I know, if I pass disposable object to using()
construct, then Dispose()
method gets called automatically at the closing bracket:
A a = new A();
using (a)
{
//...
}//<--------- a.Dispose() gets called here!
//here the object is supposed to be disposed,
//and shouldn't be used, as far as I understand.
If that is correct, then please explain the output of this program:
public class A : IDisposable
{
int i = 100;
public void Dispose()
{
Console.WriteLine("Dispose() called");
}
public void f()
{
Console.WriteLine("{0}", i); i *= 2;
}
}
public class Test
{
public static void Main()
{
A a = new A();
Console.WriteLine("Before using()");
a.f();
using ( a)
{
Console.WriteLine("Inside using()");
a.f();
}
Console.WriteLine("After using()");
a.f();
}
}
Output (ideone):
Before using()
100
Inside using()
200
Dispose() called
After using()
400
How can I call f()
on the disposed object a
? Is this allowed? If yes, then why? If no, then why the above program doesn't give exception at runtime?
I know that the popular construct of using using
is this:
using (A a = new A())
{
//working with a
}
But I'm just experimenting, that is why I wrote it differently.
Dispose() does not get called in the attached code. Further more the exception that is thrown is not handled and the program blows up.
: 'Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application.
Dispose() will not be called automatically. If there is a finalizer it will be called automatically. Implementing IDisposable provides a way for users of your class to release resources early, instead of waiting for the garbage collector.
The Dispose method performs all object cleanup, so the garbage collector no longer needs to call the objects' Object. Finalize override. Therefore, the call to the SuppressFinalize method prevents the garbage collector from running the finalizer. If the type has no finalizer, the call to GC.
Disposed doesn't mean gone. Disposed only means that any unmanaged resource (like a file, connection of any kind, ...) has been released. While this usually means that the object doesn't provide any useful functionality, there might still be methods that don't depend on that unmanaged resource and still work as usual.
The Disposing mechanism exist as .net (and inheritly, C#.net) is a garbage-collected environment, meaning you aren't responsable for memory management. However, the garbage collector can't decide if an unmanaged resource has been finished using, thus you need to do this yourself.
If you want methods to throw an exception after the object has been diposed, you'll need a boolean to capture the dispose status, and once the object is disposed, you throw the exception:
public class A : IDisposable
{
int i = 100;
bool disposed = false;
public void Dispose()
{
disposed = true;
Console.WriteLine("Dispose() called");
}
public void f()
{
if(disposed)
throw new ObjectDisposedException();
Console.WriteLine("{0}", i); i *= 2;
}
}
The exception is not thrown because you have not designed the methods to throw ObjectDisposedException
after Dispose
has been called.
The clr does not automagically know that it should throw ObjectDisposedException
once Dispose is called. It's your responsibility to throw an exception if Dispose has released any resources needed for successful execution of your methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With