views:

253

answers:

10

I've read and I believe I understand what C#'s using statement does (please correct me if I'm wrong): Initializes an IDisposable object as read only to a limited scope (the using block). I know you can initialize before the using and that doesn't limit the scope, but that is advised against here:

http://msdn.microsoft.com/en-us/library/yh598w02.aspx

I'm not always paying attention to what classes are subclasses of what. I'm not too sure what classes inherit from IDisposable. I'm not just curious what classes can be used in a using statement, but what classes would my coworkers expect to find in a using block? What classes should be in a using block? Also, is there really anything wrong with not using a using block and not calling Dispose? Is it just about memory or also stability?

+1  A: 

At least, all class that used non managed resources

Gregoire
why the downvote?
Gregoire
+12  A: 

It's not about memory. It's about other resources such as file handles, database connections etc.

Basically if a class implements IDisposable, that's a signal that you should dispose of it when you're done, because it may have unmanaged resources which would be expensive to leave around. (e.g. your connection pool may run out of connections, or a file handle will stay open, preventing another piece of code from opening the same file again).

Jon Skeet
When a class implements Idisposable, what happens? Are they given a "special" destructor, GC cleans them up faster? etc etc? Lets say I have a class, and I work with opening/closing files. Implementing idisposable will do what for me? sorry, student here :P
masfenix
@maxfenix: You might want to ask that as a separate question. (Click "Ask Question" at the top of the page.)
Daniel Pryden
@masfenix: Put shortly, *nothing special*. `IDisposable` is **just another interface**, it's only special in that there's a special language element (the `using` block) that addresses that idiom directly. While there are suggested design patterns around *how* to implement the interface, there is nothing actually special about it. The GC does nothing with it directly.
Adam Robinson
@Adam Robinson: Actually, there is nothing special technically with it. However, semantically, if a class implements `IDisposable`, you must call Dispose. That's what the contract is about. So it is in fact a little more than just an interface.
@ToxicAvenger: You're correct, of course, but that wasn't the point; @masfenix asked if there was anything actually special about the interface ("special" destructor, GC cleans them up faster, etc.), and the answer to that is "no".
Adam Robinson
@Downvoter: Care to give a reason?
Jon Skeet
+1  A: 

There is absolutely a lot wrong with not using a using block and not calling Dispose, you most likely will leak memory and / or resources. Using is a convenience, but you really should call Dispose in any object which class derives from IDisposable.

Otávio Décio
And do so in a finally{} block
Mike Atlas
Actually if an error arises in a using block, dispose is automatically called and not needed to be called in a finally block, check the link I included in the question.
Corey Ogburn
A: 

you need not to worry about using what classes under using blocks. If the you have used under using statement doesnot implements IDisposbale then it will show you red/blue wave. So that you can come to knwo that its lacking idisposable interface. And as far as i have used almost all classes of framework has Idisposable implemented. but in custom class , you need to implement

Amit Ranjan
where i am wrong. Could you please explain me.
Amit Ranjan
I'm not the down vote, but I'm guessing it's because your answer may encourage laziness in disposing the framework classes. Just because they implement the disposable pattern doesn't mean it's ok to not dispose of them when you're done.
Tesserex
Using does all the things try-catch and dispose. If i am right
Amit Ranjan
@Amit: Your answer is not easy to understand. But it sounds like you are trying to say that you should always put any object in a `using` block by default, and only remove the `using` block if the compiler flags it as an error (because the object doesn't implement `IDisposable`). You are correct, and I've upvoted you, but bear in mind that there are more complex scenarios (e.g. where you are creating an object that will be owned by a class instance) where you need more than just a `using` block.
Daniel Pryden
Yes, I know that but in case general scenarios take for the time being complex scenarios apart. I am wrong or right. In most of the cases if we use using statement then try - catch and disposed are called. For example using(sqlconnection conn = new sqlconnection){}. we do not need to specify the try catch and dispose. using will automatically take care of these things. but for safety we dispose connection object at the end of the using ...
Amit Ranjan
This answer doesn't make much sense. First of all, it's certainly untrue to say that "almost all classes of [the] framework has [have] `IDisposable` implemented". As for @Daniel's point, he's talking about scenarios where the lifetime of the object extends beyond a single method call. Nobody is talking about exceptions, but your statement is correct.
Adam Robinson
+1  A: 

As far as what classes are disposable, you can probe intellisense yourself, or you'll just learn from experience. Some common ones include Image and its children, in fact most of System.Drawing namespace, plenty of file streams, database connections, etc.

As far as when it should be called - as soon as possible. If you know it's disposable, and you know you're done with it, then call Dispose.

I believe many of the .NET base classes that implement IDisposable implement the disposable pattern, which means that they will be disposed of, properly, when the garbage collector comes to get them. But even so, you should still dispose of things when you're done, because

  1. You may leave a reference hanging around (a leak) and it won't be disposed, or
  2. The GC may not come around for a while.

Additionally, for classes you write yourself, garbage collection does NOT equate to proper disposal for unmanaged resources - a common confusion. The disposable pattern needs to be implemented yourself.

Tesserex
+1  A: 

The main reason a class would implement IDisposable is to release non managed resources. The garbage collector will release managed resources as they go out of scope and it sees fit, but it has no knowledge of non managed resources. Calling the Dispose method will explicitly release the resources.

If you do not use a using block or call the Dispose method then you will have a problem with memory leakage, which in turn could cause stability issues.

You should use a using block at all times when dealing with classes that implement IDisposable. Although you may prefer a Try.. Catch.. Finally ensuring that you call Dispose in the finally block so you can deal with exceptions.

Chris Diver
+1  A: 

You should always call Dispose on any class that implements IDisposable, and this is most easily done via a using block.

This is not just about memory. This is also not just about resources. This is about correctness.

StreamWriter is a famous example. Microsoft has even developed an MDA to catch some cases where programmers forgot to call Dispose. This is more than just memory or resources: in the StreamWriter example, a file being written may be truncated.

I had to track down a nasty bug one time (in my boss' code, actually), where a database transaction was being rolled back... turns out the cause was that Dispose wasn't being called, so it was trying to commit too much to disk when the process exited (there's a timeout for finalizers during process exit). The fix was just a few using blocks.

A third example: Microsoft's Managed ESENT wrapper classes have a "three tier" disposal scheme that requires Dispose to be called in the correct order ("outer" classes last).

So, there are three real-world examples where incorrect behavior will result if Dispose is not called properly. Other classes may exibit similar behavior.

As a general rule, you should always call Dispose.

Stephen Cleary
+12  A: 

Strictly speaking, any object that implements IDisposable and whose scope is limited to that function should be within a using block. The IDisposable interface exists to allow classes that deal with unmanaged resources (database connections, file handles, window handles, etc.) to dispose of these resources in a timely, deterministic fashion.

There are, in general, three ways in which an IDisposable object is used within a class:

  1. The object is both created and no longer needed within the scope of a single method call. This is quite common, and is when using can (and should) be used.
  2. The object is created by the class (or is passed to the class), and its lifetime extends beyond the scope of a single method call but not beyond the life of the class. For example, your class creates a Stream and needs to use it over the lifetime of the object. In this case, your class should implement IDisposable itself and dispose of the object(s) that you own when your own Dispose method is called. An example of this would be something like System.IO.StreamWriter
  3. The object is passed to the class, but the class doesn't "own" it. This means that the IDisposable object's usable lifetime is beyond the scope of a single method call, and may be beyond the lifetime of your object. In this case, someone else must be responsible for calling Dispose.

The first case is the most common that you'll encounter, which is why the using block exists. It takes care of ensuring that the object will be disposed of, even in the case of an exception.

Some examples:

  • Stream classes
  • Database connections/commands
  • Controls

There's no exhaustive list of classes that implement IDisposable, as that list would be fairly large and filled with classes that you'll likely never encounter. Think about what the class does; does it open some sort of connection or file that needs to be closed? In general, does it acquire some kind of resource that needs to be released? If so, it probably implements it. At a basic level, if the compiler allows you to enclose it in using, then it implements IDisposable.

As to the consequences of not calling Dispose, don't consider it. Call Dispose. True, the defensive standard is that if your class uses unmanaged resources directly, then you should define a finalizer that will call dispose in the event that your object is collected and someone has failed to call it, but that should not be a design choice. Ever, as far as I'm aware.

Adam Robinson
+1: Great answer.
Brian Gideon
Always call dispose? What if the `IDisposable` doesn't clean anything up and I know I'm always dealing with the concrete (thinking something like `SqlCommand` here).
Marc
@Marc: If the class implements `IDisposable`, then there's a reason for it. While `SqlCommand`'s specific implementation of `Dispose(bool)` may look bare, the same may not be the case if you were to swap in a different command class. You lose *nothing* by following the recommended guidelines, and the upside is that you're consisistent and won't have people pointing and laughing at the fact that you're not disposing of your objects properly.
Adam Robinson
A: 

A ready-reckoner of classes to call with using is:

  • Streams
  • Database connections, commands and data readers
  • Readers and Writers

There are many many more classes which you should also Dispose, but those above are frequently used, often in narrow usage scope.

Yes - there are issues with not using using and not calling dispose. A classic is a web app which does not close its connections to a database, effectively sucking resources from the database server as it holds connections open.

Neil Moss
+1  A: 

The purpose of IDisposable is to enable objects that interact with unmanaged resources (like files, databases, or graphics contexts) to clean up after themselves. A using statement is a convenient shorthand for the following construct

var disposable = new MemoryStream();
try
{
  //do some work with the disposable object
}
finally
{
  if (disposable!=null)
     disposable.Dispose();  
}

The problem of course is knowing which objects implement IDisposable...unfortunately there is no automated way to know besides the docs. Although I believe there is an Fxcop setting that will check for IDisposables used outside of a using.

Mike Brown