Try..Catch…Now What

Grrrrr.  This is a little bit of a rant.  I don't get it.  I'm working on a project right now that has code like this:

public SqlConnection GetYourFavoriteConnection()
{
  SqlConnection Conn;
  try
  {
    Conn = new SqlConnection(connString);
    Conn.Open();
  }
  catch (Exception e)
  {
    throw new Exception(e.Message, e);
  }
  return Conn;
}

Just to be clear, I'm focusing on the use of the try...catch block only.  The project I'm working on is riddled with this shit code.  Why is it shit code? Well, what was wrong with the original exception? Not good enough for your code?? Not as cool as a "new" Exception?? Am I missing something?

My Beef

Where's the value add? What's the point of catching an exception if you're not going to do anything with it?  Here's another good one,

SqlConnection Conn;
try
{
  //do stuff with Conn
}
catch(Exception e)
{
  throw new Exception(e.Message, e);
}
finally
{
  if (Conn != null)
  {
    Conn.Close();
  }
}

I've blogged about this before and apparently I'm blogging about it now. The using statement will do heavy lifting for you.  The above could be rewritten like this:

using (SqlConnection Conn = new SqlConnection("connection string"))
{
  //do stuff with Conn here
}

What's So Special About 'Using'??

The following code:

using System;
using System.Data.SqlClient;
namespace ConsoleApplication1
{
  public class Program
  {
    public static void Main(string[] args)
    {
      using (SqlConnection cn = new SqlConnection("connection string"))
      {     	
      }
    }
  }
}

...produces this IL

.method public hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       34 (0x22)
  .maxstack  2
  .locals init ([0] class [System.Data]System.Data.SqlClient.SqlConnection cn,
           [1] bool CS$4$0000)
  IL_0000:  nop
  IL_0001:  ldstr      "connection string"
  IL_0006:  newobj     instance void [System.Data]System.Data.SqlClient.SqlConnection::.ctor(string)
  IL_000b:  stloc.0
  .try
  {
    IL_000c:  nop
    IL_000d:  nop
    IL_000e:  leave.s    IL_0020
  }  // end .try
  finally
  {
    IL_0010:  ldloc.0
    IL_0011:  ldnull
    IL_0012:  ceq
    IL_0014:  stloc.1
    IL_0015:  ldloc.1
    IL_0016:  brtrue.s   IL_001f
    IL_0018:  ldloc.0
    IL_0019:  callvirt   instance void [mscorlib]System.IDisposable::Dispose()
    IL_001e:  nop
    IL_001f:  endfinally
  }  // end handler
  IL_0020:  nop
  IL_0021:  ret
} // end of method Program::Main

Notice anything?? Like the try..finally?? Ya, the using statement will put those in for you.

It Calls Dispose For You, So What?

Well for one that means less code to write.  Read here for the other.  For those who do not trust the documentation here's the code for Dispose as seen through Reflector:

protected override void Dispose(bool disposing)
{
    if (disposing)
    {
        this._userConnectionOptions = null;
        this._poolGroup = null;
        this.Close();
    }
    this.DisposeMe(disposing);
    base.Dispose(disposing);
}

Take note of the fact that it calls Close for you. No need to code for it...

 
Author: , 0000-00-00