Monday, June 14, 2004

Try/Finally for cleaner cleanup.

One thing that people often overlook is how a try/finally block can make your code both more readable and more robust. It's a great tool for cleanup code. You can see me using it on the GetErrorMessage on my WinHTTPException class. If you look carefully, you'll see that I close the handle after the return statement.
As a sample, suppose you need to read some temporary information from a file and return it as a string. No matter what happens, you need to delete this file, because it's temporary. This kind of return & cleanup begs for a try/finally block.

Let's see the simplest possible code without using try/finally:

string ReadTempFile(string FileName)
{
string fileContents;
using (StreamReader sr = new StreamReader(FileName))
{
fileContents = sr.ReadToEnd();
}
File.Delete(FileName);
return fileContents;
}


This code also has a problem when an exception is thrown on, e.g, the ReadToEnd method. So, I've actually saw some people trying to solve it coding as this:

string ReadTempFile(string FileName)
{
try
{
string fileContents;
using (StreamReader sr = new StreamReader(FileName))
{
fileContents = sr.ReadToEnd();
}
File.Delete(FileName);
return fileContents;
}
catch (Exception)
{
File.Delete(FileName);
throw;
}
}


The code is becoming complex and it's starting to duplicate code.

Now, see how much cleaner and robust is the try/finally solution:


string ReadTempFile(string FileName)
{
try
{
using (StreamReader sr = new StreamReader(FileName))
{
return sr.ReadToEnd();
}
}
finally
{
File.Delete(FileName);
}
}


Where did the fileContents variable go? It's not necessary anymore, because we can return the contents and the cleanup code executes after the return point. This is one of the advantages of having code that can run after the function returns: you can clean resources that may be needed for the return statement.

Comments:
This Try/Finally example is a good tip.

Obrigado
 
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?