ASP.NET Hosting

Exception handling and resource protection with try..finally

Paul Sheriff has just published an example he uses to recommend the use of try..finally blocks. Here is his example:

private void CreateLogFile()
{
  try
  {
    StreamWriter sw =
      new StreamWriter(@"D:\Samples\Test.txt",
      true, System.Text.UTF8Encoding.UTF8);

    sw.WriteLine("This is some text");
    sw.Close();
  }
  catch(Exception ex)
  {
    throw ex;
  }
}

Here is how I'd rewrite this example if we want to stick to try..finally:

private void CreateLogFile()
{
  StreamWriter writer;

  writer = new StreamWriter(@"D:\Test.txt",
    true, System.Text.UTF8Encoding.UTF8);
  try
  {
    writer.WriteLine("This is some text");
  }
  finally
  {
    writer.Dispose();
  }
}

Why would I rewrite the example this way?

  1. No need to protect resources that haven't been allocated. The finally block is useful only if the creation of the writer works. So the try..finally block should start immediately after that, not before.
    See http://weblogs.asp.net/fmarguerie/archive/2004/08/13/214135.aspx
  2. Use "throw", not "throw ex". If you use "throw ex", you lose the original stack trace.
    See http://www.tkachenko.com/blog/archives/000352.html
  3. The "catch" block is useless here because it does nothing except letting the exception flow.
  4. No need to test if (writer != null) because if we are in the finally block the writer has been created successfully. If the writer is not created, the finally block is never executed because we'd get out of the method due to an exception before the try..finally block.
  5. It's better to use Dispose in most cases. It calls Close and may perform other cleaning operations. Close is just fine in this example, though.

Of course, we can use the using pattern to make the code even better:

private void CreateLogFile()
{
  using (StreamWriter writer = new StreamWriter(@"D:\Test.txt",
    true, System.Text.UTF8Encoding.UTF8))
  {
    writer.WriteLine("This is some text");
  }
}

Note that VB has Using too now.

2 Comments

  • Nice post, just one remark, I looked at the original Paul Sheriff post, and it seems that you copied the first part, where he is not using the 'finally' block, rather than his actual example.

    And finally, the effortless way to do it, as you mention it, is to use 'using', which will act like a try/finally and automatically call the Dispose method.

    Ben

  • Except that Paul Sheriff's version comes with useless "StreamWriter sw = null" and "if (sw != null)".
    That's why I provided another, streamlined, version. See my notes above ("Why would I rewrite the example this way?").

Comments have been disabled for this content.