views:

5139

answers:

5

Simple best practice question.

Should you nest try catch statements or just use methods.

For instance, if you have a method that opens a file does work and closes the file, you would have the open and close outside the try catch, or rather the close in the finally block.

Now if your open method fails, the method would assert right? So should your wrap that in a try catch block or should that be called from another method, which in turn as a try catch block?

+1  A: 

Depends on what you are trying to do, but in most cases, nested try/catches are a sign of an over-complex function (or of a programmer who doesn't quite know how exceptions work!).

In the case of the open file, I'd use an IDisposable holder and a using clause, and so forgo the need of any explicit try/catch.

Pontus Gagge
+4  A: 

This is a style question but for me I try to never have more than one level of try/catch/finally nesting in a single method. At the point you hit a nested try, you've almost certainly violated the 1 function = 1 operation principal and should use a second method.

JaredPar
I think in many, if not most developers, it won't be a matter of style. It will be a matter of not understanding exceptions in .NET, and thinking they need to catch every exception, as in Java. In most case, it's best to just let the exception propagate.
John Saunders
+4  A: 

In the context of a method that opens a file I would use a using statement vs a try catch. The using statement ensures that Dispose is called if an exception occurs.

using (FileStream fs = new FileStream(file, FileMode.Open))
{
    //do stuff
}

does the same thing as:

FileStream fs;
try
{
     fs = new FileStream(file, FileMode.Open);
     //do Stuff
 }
 finally
 {
        if(fs!=null)
           fs.Dispose();
 }
cgreeno
Close, but the try/finally code doesn't quite match the using code. You need to wrap it in an anonymous scope block, as well.
Joel Coehoorn
A: 

Most of the time I would break up the nested try/catch blocks into functions. But I have sometimes written code to catch and log all uncaught exceptions thrown by my application. But what if the logging code fails? So I have yet another try/catch around that just to prevent the user from seeing the default .NET unhandled exception dialog box. But even this code could very easily be refactored into functions instead of nested try/catch blocks.

try
{
    try
    {
        DoEverything(); 
    }
    catch (Exception ex)
    {
        // Log the exception here
    }
}
catch (Exception ex)
{
    // Wow, even the log is broken ...
}
Brian Ensink
If your logging is broken, then you should let the exception propagate so the user can complain that your logging is broken!
John Saunders
I can still show the exception thrown by logging code. Its just that *I* want to do it instead of letting the framework error window come up.
Brian Ensink
+2  A: 

Now that we have lambdas and type inference and some other stuff, there's an idiom that is common in other languages which now makes a lot of sense in C#. You're example was about opening a file, doing something to it, and then closing it. Well, now, you can make a helper method which opens a file, and also takes care of making sure to close / dispose / clean up, but calls out to a lambda you provide for the "do stuff" portion. This will help you get the complicated try/catch/finally dispose/cleanup stuff right in one place, and then use it over and over.

Here's an example:

public static void ProcessFile(string filePath, Action<File> fileProcessor)

{

 File openFile = null;

 try
 {
      openFile = File.Open(filePath); // I'm making this up ... point is you are acquiring a resource that needs to be cleaned up after.

      fileProcessor(openFile); 
 }
 finally
 {
      openFile.Close(); // Or dispose, or whatever.
 }

}

Now, callers of this method don't have to worry about how to open the file or close / dispose of it. They can do something like this:

Helpers.ProcessFile("C://somefile.txt", f => 
 {
      while(var text = f.ReadLine())
      {
           Console.WriteLine(text);
      }
 });
Charlie Flowers