“Objects in System.Reflection are closer than they appear.”
by Greg McCoy

Posts Tagged ‘Code’

IDisposable Cheat Sheet

I was having a conversation with my boss a while back and he asked if we could discuss the using block a bit and any resonant patterns to its usage.

We discussed what it was, why, and how there should be some list out there indicating what is to be scoped with using() that may typically be forgotten.

Obviously, I can't dig into your proprietary code to show you your own IDisposables, and I'm not willing to list out every CLR IDisposable derived type. What I can do, however, is list what commonly used classes are IDisposable and why.

The What

I'm assuming by the fact that you're here, you know what IDisposable and the using block are. If not, here's a very brief overview.


IDisposable is the ever-impressive interface that informs your code that the type that it is applied to has explicit instruction on what is to happen in the case of its untimely demise.

Now, as .NET developers, most of us know this. In many cases, however, we haven't a clue as to what it really means, or why it matters. The reason for this is that, in the vast majority of cases, we are writing strictly managed code — managed code behaves differently than unmanaged code.

The using() Block

Wrapping up code that uses an IDisposable object is as elegant as can be. Simply do the following.

using (var mine = new MyClass())

After this block executes, the declared variable will invoke its Dispose() method, thereby running any needed finalization/disposal logic.

The Why

In managed code, the Garbage Collector is mostly self-sufficient and can usually handle getting rid of your pesky leftovers.

In unmanaged code, however, the GC is actually quite lost. It needs explicit knowledge of things that are beyond it's reflective capabilities… not beyond yours, though.

By indicating that a type is disposable, you gain the responsibility of adding a Dispose() method to your type that tells the CLR how to get rid of your unmanaged resources.

There are also classes that need to be disposed of in order to clean themselves up and out of a hierarchy. These types will essentially make whatever updates and notifications needed to other objects that may be using them, indicating that they are being disposed of, and won't be around for dessert.

The Classes

The following is by no means an exhaustive listing of the classes that implement IDisposable (nor a copy and paste of the Object Browser). This is hopefully a catalog of the most common disposable objects whose scope need to be explicitly defined.

Class Reason
Microsoft.ServiceModel.Channels.Mail.MailTransport Communication
System.Data.Common.DbCommand Communication
System.Data.Common.DbConnection Communication
System.Data.Common.DbDataReader Communication
System.Data.Common.DbTransaction Communication
System.Data.Linq.SqlClient.SqlProvider Communication
System.Data.OleDb.OleDbCommand Communication
System.Data.OleDb.OleDbConnection Communication
System.Data.SqlClient.SqlDataReader Communication
System.Diagnostics.Eventing.Reader.EventRecord Hardware (Memory)
System.Drawing.Brush Hardware (GDI)
System.Drawing.Font Hardware (GDI)
System.Drawing.Graphics Hardware (GDI)
System.Drawing.Image Hardware (GDI)
System.IO.BinaryReader File System
System.IO.BinaryWriter File System
System.IO.Stream File System
System.IO.StreamReader File System
System.IO.StreamWriter File System
System.IO.TextReader File System
System.IO.TextWriter File System
System.Net.FtpWebResponse Communication
System.Net.Mail.MailMessage Communication
System.Net.Sockets.TcpClient Communication
System.Net.Sockets.UdpClient Communication
System.Net.WebResponse Communication
System.Security.Cryptography.HashAlgorithm Hardware (Memory)
System.ServiceModel.ChannelFactory Communication
System.ServiceModel.Channels.Message Communication
System.ServiceModel.ClientBase Communication
System.Threading.Timer Hardware (CPU)
System.Web.UI.Control Notification
System.Windows.Forms.Control Hardware (GDI)
System.Xml.XmlReader File System
System.Xml.XmlWriter File System

Custom Classes

It is also very important to note that the use of these classes inside your own as members warrants implementing IDisposable on your own classes as well.

Having one or more disposable objects inside your class is, essentially, making your own class dependant on the resources (sockets, threads, the file system, etc...) that those objects need help cleaning up.

What else?

I will continue adding additional classes as they either become more common in my own use, or are requested. Not all developers write the same type of code, so this list obviously won't cover everything important by my hand alone. Please feel free to leave comments for others that I've left out and you think should be included.

Arguments on antidepressants…

I was coming into a few problems with backslashes and quotes not playing consistently nice for snippet input. So I set out to find out why. I ran across a few interesting facts about command line arguments while trying to figure out the best (most reliable) way to escape them for snippet input. The following is an excerpt from tenouk.com

  • For information, Microsoft uses Microsoft C Runtime (CRT) for C codes; that is Microsoft C version (mix of standard C and Microsoft C).
  • Microsoft C startup code uses the following rules when interpreting arguments given on the operating system command line:
  1. Arguments are delimited by white space, which is either a space or a tab.
  2. A string surrounded by double quotation marks is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument. Note that the caret (^) is not recognized as an escape character or delimiter.
  3. A double quotation mark preceded by a backslash, \“, is interpreted as a literal double quotation mark ().
  4. Backslashes are interpreted literally, unless they immediately precede a double quotation mark.
  5. If an even number of backslashes is followed by a double quotation mark, then one backslash (\) is placed in the argv array for every pair of backslashes (\\), and the double quotation mark () is interpreted as a string delimiter.
  6. If an odd number of backslashes is followed by a double quotation mark, then one backslash (\) is placed in the argv array for every pair of backslashes (\\) and the double quotation mark is interpreted as an escape sequence by the remaining backslash, causing a literal double quotation mark () to be placed in argv.

This is quite interesting. I knew there must be a better way, however. Fortunately, I was correct. I found the following frustration post on the MSDN forums shortly after. Here’s the juicy stuff…

The static System.Environment.CommandLine will provide the original untampered cmdline – should be straight forward to use this.
there is also System.Environment.GetCommandLineArgs() method but this is used to create the args parameter passed to main and suffers the same problem , I mention it because, when you use it the element 0 of the array contains the path to the excutable which you can use to strip the exe name from the System.Environment.CommandLine

Awesome! What this gives us is a good clean way to get all of our input directly from the command line call to the snippet. The biggest problem is that I (currently) can do nothing to eliminate this problem for you. I will however be trying to come up with a better answer than that. Until then, it’s the snippet developer’s job to be sure that the input being given to the snippet is clean. Here is a pretty decent GetInput() method that should do the trick. Oh, the code below also allows the snippet to be “piped”-to, so it really is a good idea to consider using it as your input standard. The key is making sure it’s implemented. ;)

private static String GetInput(){   System.IO.Stream stream = Console.OpenStandardInput();   System.IO.StreamReader reader =      new System.IO.StreamReader(stream);   String input = reader.ReadToEnd();   if (String.IsNullOrEmpty(input))   {      String application = Environment.GetCommandLineArgs()[0];      input = Environment.CommandLine         .Substring(            Environment.CommandLine.LastIndexOf(application)            + application.Length + 2)         .Trim().Trim('\"');   }   return input;}
Get a free book about code review best practices.