views:

162

answers:

8

Three questions:

  1. What kind of variables should be disposed manually in .NET/Java? I know that SqlConnection should always be either disposed manually or used in a using{} block. Is it right? What are the other kind of variables that should be disposed?

  2. I read somewhere that unmanaged code must be disposed manually. Is that right? What exactly is unmanaged code and how do I know if a variable is managed or unmanaged?

  3. Finally, how do I dispose variables? I know that the Dispose() method does not really dispose a variable. So what does Dispose() do? Should I set them to null()? What is the logic by which the garbage collector works?

+2  A: 

.NET

  1. All objects that implement the IDisposable interface are asking that their Dispose methods are called when they are no longer required. The using block is just C# sugar for a try-finally block that disposes the IDiposable in the finally block, as long as it is not null. Consequently, disposal occurs even if an exception is thrown in the try block.

  2. Unmanaged Code.

  3. The Dispose method does whatever code the developer who wrote the Dispose method put in it! Typically this involves releasing 'unmanaged' resources, which are not managed by the runtime, such as database connections, window handles and file handles. Note that the GC manages the heap, so setting a reference to null just before the object it references becomes unreachable doesn't help all that much.

This is a good read.

Ani
+5  A: 

This answer deals only with the .NET part of your question

What kind of variables should be disposed manually in .NET/Java? I know that SqlConnection should always be either disposed manually or used in a using{} block. Is it right? What are the other kind of variables that should be disposed?

In .NET, all objects that implement IDisposable should be disposed explicitly (or used in a using block).

I read somewhere that unmanaged code must be disposed manually. Is that right? What exactly is unmanaged code and how do I know if a variable is managed or unmanaged?

You probably mean unmanaged resources, as code can't be disposed... All classes that use unmanaged resources (memory allocated not on the managed heap, win32 handles...) should implement IDisposable, and should be disposed explictly, since they are not managed by the garbage collector.

Finally, how do I dispose variables? I know that the Dispose() method does not really dispose a variable. So what does Dispose() do? Should I set them to null()? What is the logic by which the garbage collector works?

I'm not sure I understand your question... you don't dispose a variable, it is managed by the garbage collector. All managed memory is automatically released when it's not used anymore (i.e. it is not accessible by code because there are no references left to it). The IDisposable.Dispose method is only intended for resources that are not managed by the GC.


EDIT: as a side note, I would like to add that IDisposable is primarily intended to clean-up unmanaged resources, but is also frequently used to perform other cleanup actions and guarantee state or data integrity. For instance, IDbTransaction implements IDisposable in order to rollback the transaction if an exception occurs before the transaction was committed :

using (var trx = connection.BeginTransaction())
{
    // Do some work in the transaction
    ...

    // Commit
    trx.Commit();

} // the transaction is implicitly rolled back when Dispose is called
Thomas Levesque
+3  A: 

In Java, you "close" rather than "dispose".

  • JDBC Connections, unless you got them from a pool.
  • JDBC ResultSets, depending on the JDBC connector.
  • InputStreams, OutputStreams, Readers and Writers (with the exception of those that are byte array and string backed).

Some third-party Java libraries or frameworks have classes that need to be manually disposed / closed / destroyed.

Stephen C
In addition, here's a partial list of certain resources that must be disposed explicitly: http://stackoverflow.com/questions/2486200
trashgod
+1  A: 

This was mostly covered by Thomas, but to expand on the third point:

Finally, how do I dispose variables? I know that the Dispose() method does not really dispose a variable. So what does Dispose() do? Should I set them to null()? What is the logic by which the garbage collector works?

They key is that the Dispose() tells the object to free any unmanaged resources that it currently holds, it does not free the object itself.

The garbage collector knows how to free the object, but for IDisposable objects, only the object itself knows how to dispose of it's private resources, so you have to make sure that Dispose() gets called before the garbage collector frees the object.

Douglas
A: 

For Java:

SWT is a framework where we have to dispose resources (like images), because the framework uses native libs and system handles which have to released. SWT classes are documented and tell, when dispose is required.

Andreas_D
A: 

Following up on other .NET solutions...

If your object owns unmanaged resources, it's not enough to simply clean them up on Dispose() calls, because you have no guarantee that Dispose will get called. The full solution is:

  1. Add a finalizer for the class.
  2. Add a public bool property called Disposed, which indicates that the object has been disposed.
  3. Add a protected Dispose(bool) method. The public Dispose() method has no parameters.
  4. When Dispose() is called, if the Disposed property is false, it will call Dispose(true), and call GC.SuppressFinalize() to disable the finalizer. Ths is essential to keep .NET's garbage collector happy. Classes with unspressed finalizers go to the end of the line for garbage collector cleanup, so they become almost a memory leak.
  5. The public Dispose() method should then set the Disposed property to true.
  6. The finalizer calls Dispose(false).
  7. The Dispose(bool) will always clean up its own managed resources, but it will clean up unmanaged resources only when called as Dispose(true). Note that all resource cleanup is in the protected Dispose(bool) method, not in the public Dispose() method.
  8. If the class is not sealed, then the protected Dispose(bool) method should be a virtual method. Subclasses that need to do cleanup can override Dispose(bool) and followht e same logic as above. In addition, they should call base.Dispose(bool) with the parameter they were given.
Cylon Cat
A: 

If .net, if you can use an object in a "using" statement, that means the object implements iDisposable and you should when practical call it's disposal method when you're done with it. Note that the disposal method may not always be called "Dispose", but you can always call it by casting the object to iDisposable and then calling Dispose on that.

Note that some types of "iDisposable" objects don't handle any unmanaged resources, but do subscribe to events. If such an object isn't properly disposed, it might not get garbage-collected unless or until all of the objects for which it holds subscribed events are themselves garbage-collected. In some cases, that may never happen until an application exits.

For example, the enumerator returned by an iEnumerable collection might subscribe to that object's "collection changed" event, unsubscribing when its dispose method is called. If the dispose method is never called, the enumerator would remain around as long as the collection did. If the collection itself stayed around a long time and was enumerated frequently, this could create a huge memory leak.

supercat
An enumerator of IEnumerable is also likely enough (given the wide range of sources) to hold onto either an unmanaged resource or a managed object which in turn holds onto an unmanaged resource. Enumerators holding onto streams and datareaders are pretty common. It's also very common for enumerators to not need to be disposed at all, but calling an empty dispose is less wasteful than checking if an enumerator is disposable and then calling it, so it makes sense for IEnumerator<T> to inherit IDisposable.
Jon Hanna
@Jon Hanna: Incidentally, what should an iEnumerable do if it requires disposal for safe operation and an effort is made to call the non-generic GetEnumerator (whose return is not an iDisposable)? Should it throw a NotImplementedException, generate a new List containing the entire enumerated contents of the item (using the safe GetEnumerator<T>) and then enumerate that, or do something else?
supercat
@supercat. It should implement IDisposable, and the calling code should call `if(e is IDisposable)((IDisposable)e).Dispose()` when it is finished with it. The most common way to use an enumerator is of course with the language-supplied `foreach` syntax (and equivs in different languages) and `foreach` does test for IDisposable in this way. This logical requirement was not clear before though and also testing is more expensive than calling an empty method, hence the generic interface being more explicit by inheriting from IDisposable.
Jon Hanna
@Jon Hanna: If an object implements iEnumerable(of T), as distinct from iEnumerable, it is required to implement iDisposable. I would expect that "modern" code will use iEnumerable(of T). If iEnumerable.GetEnumerator is called, it's likely the calling code won't call iDisposable.Dispose. What, then, should the enumerator do in such case?
supercat
To begin with, that this case only counts if code directly manipulates the IEnumerator object, as foreach will (A) call Dispose on IEnumerator<T> and (B) test for IDisposable and call Dispose if it can, for IEnumerator.Now code that is hand-written to use IEnumerator directly may not do (B). Of course, it may not do (A) either. The big difference is that not doing (A) is more clearly wrong than not doing (B). Making it clear that (B) is wrong is precisely why IEnumerator<T> was defined in terms of IDisposable. Ultimately, all one piece of code can do is assume it was used correctly.
Jon Hanna
A: 

I'm in agreement with the above, I'll just add to the subsequent question about setting a variable to null.

You don't need to do this with variables used in a method (they will fall out of scope so it's only if they have state within them that must be signalled as needing clean-up, through IDisposable.Disopse that you have to worry abou this).

It's rarely useful for instance or static members, as memory isn't as precious a resource as people often think (it is a precious resource, but most attempts to deal with it in a few lines of code is like turning off your taps while you've a burst main.

It is though useful if you have a static or instance member of a class and (A) it is a large object (B) the "owning" object is likely to stay in memory for a long time and (C) you know you won't need that value gain, to set that member to null.

In practice this isn't a very common combination. If in doubt, just leave alone.

Now, do read the other answers here, as what they say about the Dispose() method is much more important.

Jon Hanna