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.
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.
A typical Dispose() implementation only calls Dispose() on any objects that it stores in its fields that are disposable. Which in turn release unmanaged resources. If you implement IDisposable and not actually do anything, like you did in your snippet, then the object state doesn't change at all. Nothing can go wrong. Don't mix up disposal with finalization.
The purpose of IDisposable is to allow an object to fix the state of any outside entities which have, for its benefit, been put into a state that is less than ideal for other purposes. For example, an Io.Ports.SerialPort object might have changed the state of a serial port from "available for any application that wants it" to "only usable by one particular Io.Ports.SerialPort object"; the primary purpose of SerialPort.Dispose is to restore the state of the serial port to "available for any application".
Of course, once an object that implements IDisposable has reset entities that had been maintaining a certain state for its benefit, it will no longer have the benefit of those entities' maintained state. For example, once the state of the serial port has been set to "available for any application", the data streams with which it had been associated can no longer be used to send and receive data. If an object could function normally without outside entities being put into a special state for its benefit, there would be no reason to leave outside entities in a special state in the first place.
Generally, after IDisposable.Dispose has been called on an object, the object should not be expected to be capable of doing much. Attempting to use most methods on such an object would indicate a bug; if a method can't reasonably be expected to work, the proper way to indicate that is via ObjectDisposedException.
Microsoft suggests that nearly all methods on an object which implements IDisposable should throw ObjectDisposedException if they are used on an object which has been disposed. I would suggest that such advice is overbroad. It is often very useful for devices to expose methods or properties to find out what happened while the object was alive. Although one could give a communications class a Close method as well as a Dispose method, and only allow one to query things like NumberOfPacketsExchanged after a close but not after a Dispose, but that seems excessively complicated. Reading properties related to things that happened before an object was Disposed seems a perfectly reasonable pattern.
Calling Dispose() doesn't set the object reference to null, and your custom disposable class doesn't contain any logic to throw an exception if its functions are accessed after Dispose() has been called so it is of course legal.
In the real world, Dispose() releases unmanaged resources and those resources will be unavailable thereafter, and/or the class author has it throw ObjectDisposedException if you try to use the object after calling Dispose(). Typically a class-level boolean would be set to true within the body of Dispose() and that value checked in the other members of the class before they do any work, with the exception being thrown if the bool is true.
A disposer in C# is not the same as a destructor in C++. A disposer is used to release managed (or unmanaged) resources while the object remains valid.
Exceptions are thrown depending on the implementation of the class. If f() does not require the use of your already disposed objects, then it doesn't necessarily need to throw an exception.
Related
Sorry, I asked a similar question earlier and there were answers to it. But again I ran into this topic and it blows my head off.
So, John Sharp's book, Microsoft Visual C # Step by Step 9ed. Part 2, chapter 14.
Quote:
class Example : IDisposable
{
private Resource scarce; // scarce resource to manage and dispose
private bool disposed = false; // flag to indicate whether the resource
// has already been disposed
~Example()
{
this.Dispose(false);
}
public virtual void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
// release large, managed resource here
}
// release unmanaged resources here
this.disposed = true;
}
}
public void SomeBehavior() // example method
{
checkIfDisposed();
}
private void checkIfDisposed()
{
if (this.disposed)
{
throw new ObjectDisposedException('Example: object has been disposed');
}
}
}
Notice the following features of the Example class:
The class implements the IDisposable interface.
The public Dispose method can be called at any time by your application code.
The public Dispose method calls the protected and overloaded version of the Dispose method that takes a Boolean parameter, passing the
value true as the argument. This method actually performs the resource
disposal.
The destructor calls the protected and overloaded version of the Dispose method that takes a Boolean parameter, passing the value false
as the argument. The destructor is called only by the garbage
collector when your object is being finalized.
You can call the protected Dispose method safely multiple times. The variable disposed indicates whether the method has already been
run and is a safety feature to prevent the method from attempting to
dispose of the resources multiple times if it is called concurrently.
(Your application might call Dispose, but before the method completes,
your object might be subject to garbage collection and the Dispose
method run again by the CLR from the destructor.) The resources are
released only the first time the method runs.
The protected Dispose method supports disposal of managed resources (such as a large array) and unmanaged resources (such as a file
handle). If the disposing parameter is true, this method must have
been called from the public Dispose method. In this case, the managed
resources and unmanaged resources are all released. If the disposing
parameter is false, this method must have been called from the
destructor, and the garbage collector is finalizing the object. In
this case, it is not necessary (or exception-safe) to release the
managed resources because they will be, or might already have been,
handled by the garbage collector, so only the unmanaged resources are
released.
The public Dispose method calls the static GC.SuppressFinalize method. This method stops the garbage collector from calling the
destructor on this object because the object has already been
finalized.
All the regular methods of the class (such as SomeBehavior) check to see whether the object has already been discarded. If it has, they
throw an exception.
I have highlighted in bold a paragraph in which I cannot understand under what circumstances this is possible. In particular this:
Your application might call Dispose, but before the method completes,
your object might be subject to garbage collection and the Dispose
method run again by the CLR from the destructor.
I do not understand. If the Dispose method has not yet completed, then the operation this.disposed = true has not yet been performed, then this.disposed is still false.
The object will be garbage collected while this.Dispose (true) is running. I have already come to terms with this - the method is still working, in the still working method there are operations using the this keyword, that is, we are still working with this object, there are operations using the members of this object (this.disposed = true), and when the method ( this.Dispose (true)) completes, after it the GC.SuppressFinalize (this) code should work, which also contains the this keyword, but still, for some reason our object is subject to garbage collection as written in the book.
Good. Let's assume.
But this.disposed is still false, and when garbage collected and the this.Dispose (false) method is called from the destructor, the this.disposed field won't play any role.
Was the author wrong? Why does he write about the role of the disposed field and give an example in which this field is useless? Or am I losing my mind?
The GC will only ever release the memory of an object when it is sure that none of it's instance members will ever be invoked by code again. So while the quote is correct that it's possible for the object to have been collected before Dispose finishes executing, that's only true if there is no possible code path from where the currently executing code is that would ever reach an instance variable. So in your particular implementation, it wouldn't be able to free the memory for the object until after this.disposed = true; had already run (assuming there's no other possible means of any executable code to ever access another instance variable).
So the whole point of that assertion is to tell you that you either need to be okay with the instance being cleared before the cleanup is finished, or you need to access some instance member (which it does by setting disposed) after any operations that would expect the instance to still exist.
That said, these points are all generally rather esoteric and pretty rarely come up. If you are never accessing any instance members you're unlikely to even realize that the object's memory was technically freed before some other unmanged disposal was finished. If you were actively trying to observe the effect, you'd probably have to use something like weak references or unsafe code holding a reference to some of that instance state (which is exactly why you should avoid doing things like that whenever possible).
Consider the following code:
public Bar GetBar()
{
using(var foo = new Foo())
{
return foo.Bar;
}
}
Is this leaky, or is foo.Dispose() called? Is it possible that the return value is invalid as a result of foo being disposed?
The answers here are close but not complete and are inconsistent.
Is this leaky, or is foo.Dispose() called?
Dispose is called. The using block gets converted to a try/finally block in which foo is disposed of in the finally section. finally will be called after the try completes (whether by exception or naturally) and before returning to the caller. So Dispose will be called in virtually every situation (barring very serious exceptions such as out of memory, thread aborts, etc.)
Is it possible that the return value is invalid as a result of foo being disposed?
Sure, if Dispose does something to invalidate the object that Bar references, then yes, it certainly could be returning an "invalid" reference. But that would have to be explicit within Foo. Disposing of an object does not automatically dispose of all properties.
Is this leaky
No. This is good coding practice for almost any object implementing IDisposable because it ensures that the dispose method is called as soon as the variable being 'used' goes out of scope (eg. the code leaves the using block). There are a few exceptions (WCF clients, custom code that doesn't follow good IDisposable practices), but it is a good idea to wrap ANY IDisposable in a using block unless you have a specific reason not to.
Is it possible that the return value is invalid as a result of foo being disposed
This depends on what the Dispose method in Foo does. For example, if you try to invoke a SQLCommand that references a SQLConnection that has already been closed/disposed, you are going to get an exception. Lets look at an example that makes this behavior obvious.
public class Foo : IDisposable
{
public Foo()
{
ComplexType = new ComplexType();
}
public ComplexType ComplexType { get; set; }
public void Dispose()
{
ComplexType = null;
GC.Collect();
}
}
Now this piece of code that accesses our Foo:
static void Main(string[] args)
{
Foo foo;
ComplexType complexType;
using (var newFoo = new Foo())
{
foo = newFoo;
complexType = newFoo.ComplexType;
}
Console.WriteLine(complexType.SomeProperty); // This works :)
Console.WriteLine(foo.ComplexType.SomeProperty); // Throws an exception because ComplexType is NULL
Console.ReadKey();
}
Weird right? The reason this happens is because in the Foo constructor we create a new ComplexType and store it at a memory address. The Foo.ComplexType property contains a reference to the memory address. When we call dispose, we set the reference to null, but the actual object is not garbage collected because we have other references to it in our calling code, so we can't access it through the foo.ComplexType property anymore, but it is still accessible via the complexType variable. Note as well that foo is NOT null even though it has been assigned to an object that has been disposed. Because a reference still exists to our Foo instance, despite being outside of the using block, it is still alive since it can't be collected while that reference exists.
Now, if the Dispose method changed SomeProperty, it is possible (depending on how it was changed), that the change COULD propagate out and invalidate results.
I guess the moral of the story is that you could experience (or create) all sorts of weird behavior if you start playing around with objects that have been disposed, but that depends on what the disposed objects are doing during disposal. I wouldn't recommend it as a practice since most objects aren't intended to be used after disposal. Perform your "work" as an atomic unit inside the using block, and then let the object die.
Java
In Java, there is an idiom called "Finalizer Guardian" which prevents subclasses overriding superclasses finalizer but forgetting to invoke it. Here is an example from Effective Java Item7:
// Finalizer Guardian idiom
public class Foo {
// Sole purpose of this object is to finalize outer Foo object
private final Object finalizerGuardian = new Object() {
#Override protected void finalize() throws Throwable {
... // Finalize outer Foo object
}
};
... // Remainder omitted
}
With this technique, even if a subclass having a finalizer doesn't invoke superclass's finalizer, the private object would run the finalization code of the superclass.
C#
However, in C# in a Nutshell, section "Calling Dispose from a Finalizer", there is an example like this:
class Test : IDisposable {
public void Dispose() // NOT virtual {
Dispose (true);
GC.SuppressFinalize (this); // Prevent finalizer from running.
}
protected virtual void Dispose (bool disposing) {
if (disposing) {
// Call Dispose() on other objects owned by this instance.
// You can reference other finalizable objects here.
// ...
}
// Release unmanaged resources owned by (just) this object.
// ...
}
˜Test() {
Dispose (false);
}
}
The author also stated that:
The disposing flag means it’s being called “properly” from the Dispose
method rather than in “last-resort mode” from the finalizer. The idea
is that when called with disposing set to false, this method should
not, in general, reference other objects with finalizers (because such
objects may themselves have been finalized and so be in an
unpredictable state)
Question
But, when we review the Finalizer Guardian idiom of Java, the inner private guardian object actually referring/finalizing the outer object which could have a finalizer itself.
It violates what the author of C# in a Nutshell stated.
I am curious about why "referring other finalizable objects in a finalizer" is possible in Java but not in C#.
Thanks for answering.
First of all in C# one can't "forget" to call base class finalizer in derived class because there is no syntax to override base class finalizer - it will be called always (similar to constructors).
Indeed one can override Dispose and forget to call base class' version - in this case implementation of finalization in base class will be skipped. On other hand when properly implemented finalize-able classes in C# would not cause fatal issues if derived class forgets to dispose parent one - classes that really manage native resources (like OS handles) should be sealed and thus protected from the issue (as one can't override any methods in this case).
On second half about finalizing order:
I don't know how or if Java finalization guarantees that objects are finalized in consistent order so all references are valid till all finalizers finished...
In .Net/C# finalizers order is undefined - meaning after determining what objects need to be finalized (due to lack of external references) objects from that set will get finilizer called without any particular ordering. As result if objects in the set refer to each other than when finalizer of last object is called all other ones are already finalized.
I think it's not that simple. I think you can reference other objects in .net and java alike and the same problem exists about the other objects being in an unpredictable state. One would need to study the inner workings of both to fully understand them, but I don't know java that deeply, I only think that they are very similar. And by the way, this finalizer guardian looks fishy to me.
You don't show the code for the finalizer guardian, but I would suggest that one should avoid having a finalizable object hold a reference back to the original. Instead, those aspects of the original which would need cleanup should be encapsulated within the finalizable object (possibly using an AtomicReference or AtomicInteger). For example, an object which encapsulates an OS file handle could keep the handle itself encapsulated within a private finalizable object that holds the handle in an AtomicInteger. If the outer object gets abandoned, the handle can be cleaned up without anything having to access the outer object. If the outer object is asked to close the file, it can relay the request to the inner object, which can then read and clear the AtomicInteger where the handle is stored (thus ensuring the file can get closed only once).
I have a NHibernate repository that looks like this:
public class NHibRepository : IDisposable
{
public ISession Session { get; set; }
public ITransaction Transaction { get; set; }
// constructor
public NHibRepository()
{
Session = Database.OpenSession();
}
public IQueryable<T> GetAll<T>()
{
Transaction = Session.BeginTransaction();
return Session.Query<T>();
}
public void Dispose()
{
if (Transaction != null && Transaction.IsActive)
{
Transaction.Rollback(); // ObjectDisposedException on this line
}
Session.Close();
Session.Dispose();
}
~NHibRepository()
{
Dispose();
}
}
When I use the repository like this, it runs fine:
using (var repo = new NHibRepository())
{
Console.WriteLine(repo.GetAll<Product>().Count());
}
But when I use it like this, it will throw an ObjectDisposedException:
var repo = new NHibRepository();
Console.WriteLine(repo.GetAll<Product>().Count());
The easy solution would be to always dipose of the repository explicitly, but unfortunately I don't control the life cycle of some of the classes that use the repository.
My question is, why is the Transaction disposed of already even though I did not explicitly call Dispose()? I'd like to have the repository automatically clean itself up if it was not disposed explicitly.
My question is, why is the Transaction disposed of already even though I did not explicitly call Dispose()?
Perhaps the transaction's finalizer ran first. Remember, finalizers of dead objects can run in any order and on any thread, and need not have been correctly initialized before they are finalized. If you do not understand all the rules of finalizers then learn them all before you attempt to write any more code that uses finalizers. This is one of the hardest things to get right.
It also looks as though you have implemented the disposable pattern incorrectly, and that is going to cause you a world of grief. Read up on the pattern and do it correctly; the finalizer should not be disposing stuff that has already been disposed:
http://msdn.microsoft.com/en-us/magazine/cc163392.aspx
Lose the finalizer. Very few classes in .net need a finalizer; generally, the only .net 2.0-or-later classes which should have finalizers are those whose sole reason for existence revolves around it.
If a class with a finalizer holds an access to some other object, one of three conditions will apply when the finalizer is run:
The other object has already had its finalizer (if any) run; there's no need to dispose it, since it's already been taken care of.
The other object has a finalizer scheduled to run; there's no need to dispose it, since it will be taken care of automatically.
A reference to the other object exists outside of the object whose finalizer is running; this usually means one shouldn't dispose it.
The only time a finalizer should ever take any action to dispose of a manage object is when an outside reference is likely to exist, and the collection of the object being finalized will imply that the other object should be disposed despite the existence of that reference. That's a very rare situation.
You should put GC.SuppressFinalize(this); in your Dispose method otherwise the finalizer will dispose an already disposed object. Also, finalizers are in almost all cases only needed for unmanaged resources
The CLR makes no guarantees with respect to the order that finalizers will be called. It sees a group of unrooted objects (e.g. not reachable from any GC root) and starts calling finalizers. It doesn't matter that you have connections within your object graph. The finalizers can be called in any order. Finalizers are intended to clean up unmanaged resources, not child objects. You need to re-think your API.
You should have a member variable isDisposed that would be set to true by the Dispose() method. Then at the beginning of the Dispose() command just return if it is already set to true. According to .NET whitepapers, Dispose() could be executed multiple times without side effects and this is the way to do it.
Secondly, make the class sealed (the class is not implementing the Dispose pattern properly for inheritance) and put GC.SuppressFinalize(this); right before the isDisposed variable assignment in the Dispose() method.
public void Dispose()
{
if (isDisposed) { return; }
....
GC.SuppressFinalize(this);
isDisposed = true;
}
Is there any sense to set custom object to null(Nothing in VB.NET) in the Dispose() method?
Could this prevent memory leaks or it's useless?!
Let's consider two examples:
public class Foo : IDisposable
{
private Bar bar; // standard custom .NET object
public Foo(Bar bar) {
this.bar = bar;
}
public void Dispose() {
bar = null; // any sense?
}
}
public class Foo : RichTextBox
{
// this could be also: GDI+, TCP socket, SQl Connection, other "heavy" object
private Bitmap backImage;
public Foo(Bitmap backImage) {
this.backImage = backImage;
}
protected override void Dispose(bool disposing) {
if (disposing) {
backImage = null; // any sense?
}
}
}
Personally I tend to; for two reasons:
it means that if somebody has forgotten to release the Foo (perhaps from an event) any downstream objects (a Bitmap in this case) can still be collected (at some point in the future - whenever the GC feels like it); it is likely that this is just a shallow wrapper around an unmanaged resource, but every little helps.
I really don't like accidentally keeping an entire object graph hanging around just because the user forgot to unhook one event; IDisposable is a handy "almost-kill" switch - why not detach everything available?
more importantly, I can cheekily now use this field to check (in methods etc) for disposal, throwing an ObjectDisposedException if it is null
The purpose of Dispose() is to allow clean up of resources that are not handled by the garbage collector. Objects are taken care of by GC, so there's really no need to set the reference to null under normal circumstances.
The exception is if you expect the caller to call Dispose and hold on to the instance after that. In that case, it can be a good idea to set the internal reference to null. However, disposable instances are typically disposed and released at the same time. In these cases it will not make a big difference.
It's just about useless. Setting to NULL back in the old COM/VB days, I believe, would decrement your reference count.
That's not true with .NET. When you set bar to null, you aren't destroying or releasing anything. You're just changing the reference that bar points to, from your object to "null". Your object still exists (though now, since nothing refers to it, it will eventually be garbage collected). With few exceptions, and in most cases, this is the same thing that would have happened had you just not made Foo IDisposable in the first place.
The big purpose of IDisposable is to allow you to release unmanaged resources, like TCP sockets or SQL connections, or whatever. This is usually done by calling whatever cleanup function the unmanaged resource provides, not by setting the reference to "null".
This can make sense if you want to somehow prevent the disposed owned instance to be re-used.
When you set references to disposable fields to null, you are guaranteed to not use the instances any more.
You will not get ObjectDisposedException or any other invalid state caused by using owned disposed instance (you may get NullReferenceException if you do not check for nulls).
This may not make sense to you as long as all IDisposable objects have a IsDisposed property and/or throw ObjectDisposedException if they are used after they are disposed - some may violate this principle and setting them to null may prevent unwanted effects from occuring.
In C# setting an object to null is just release the reference to the object.
So, it is theoretically better to release the reference on managed objects in a Dispose-Method in C#, but only for the possibility to the GC to collect the referenced object before the disposed object is collected. Since both will most likely be collected in the same run, the GC will most propably recognize, that the referenced object is only referenced by a disposed type, so both can be collected.
Also the need to release the reference is very small, since all public members of your disposable class should throw an exception if the class is alreay disposed. So no access to your referenced object would success after disposing the referenced method.
In VB.NET there is sense to set to Nothing declared Private WithEvents objects.
The handlers using Handles keyword will be removed in this way from these objects.
The purpose of the dispose() is to cleanup the resources that are unmanaged. TCP connections, database connections and other database objects and lots of such unmanaged resources are supposed to be released by the developer in the dispose method. So it really makes sense.
In general no need to set to null. But suppose you have a Reset functionality in your class.
Then you might do, because you do not want to call dispose twice, since some of the Dispose may not be implemented correctly and throw System.ObjectDisposed exception.
private void Reset()
{
if(_dataset != null)
{
_dataset.Dispose();
_dataset = null;
}
//..More such member variables like oracle connection etc. _oraConnection
}