35

When writing a C# application whose #1 priority is to never crash, how often should I used a try-catch block?

Can I encapsulate all the statements in a method in try-catch blocks?

public void SomeMethod()
{
    try
    {
        // entire contents of the function
        // library calls
        // function calls
        // variable initialization .. etc
    }
    catch (Exception e)
    {
        // recover
    }
}

What are the downsides to wrapping everything in try-catch blocks?

Justin Tanner
  • 14,062
  • 17
  • 82
  • 103

13 Answers13

34

The only down side is when an exception is actually thrown. There is no overhead for wrapping the code, except for when exceptions occur.

Also, you don't want to use try/catch for control flow. Consider this (bad code):

try {

    FileStream fs = File.Open("somefile.txt", FileMode.Open);

} catch (Exception ex) {
    MessageBox.Show("The file does not exist. Please select another file");
}

You'll get more performance from some thing like File.Exists. such as:

if(!File.Exists("somefile.txt"))
  MessageBox.Show("The file does not exist.")

EDIT: found the MSDN direct quote:

Finding and designing away exception-heavy code can result in a decent perf win. Bear in mind that this has nothing to do with try/catch blocks: you only incur the cost when the actual exception is thrown. You can use as many try/catch blocks as you want. Using exceptions gratuitously is where you lose performance. For example, you should stay away from things like using exceptions for control flow.

Nikhil Agrawal
  • 26,128
  • 21
  • 90
  • 126
scottm
  • 27,829
  • 22
  • 107
  • 159
  • 2
    Well, there is *minimal* overhead. Some, but very very small. – Marc Gravell Feb 02 '09 at 23:50
  • 1
    The bad thing is that JIT compiler cannot inline functions containing exception handling constructs – Mehrdad Afshari Feb 27 '09 at 21:05
  • 17
    It is possible for the file to stop existing between when you check for it and try to open it. You *need* the try-catch block to be sure you don't crash. – Craig Gidney Feb 27 '09 at 21:24
  • @Strilanc but that's an exception that deserves to be thrown. Depending on the specific application, this case is probably very very unlikely if not completely impossible. – Louis Jun 08 '15 at 18:31
27

This is a big topic. Start here for some excellent discussion of Exception handling best practices and be prepared for a religious war...

Code Analysis Team Blog

Martin Fowler - Fail Fast

MSDN on Exception Handling

Checked vs Unchecked Exceptions

My own opinion is that for the most part you use "try/finally" a lot, but "catch" very little. The problem is that if you attempt to catch and handle Exceptions in the wrong instances, you may inadvertently put your application in a bad state. As a rule, use dev and test to learn where you actually need to handle an exception. Those will be places that you can't check. i.e. you shouldn't really need to handle nullreference or filenotfound because you can proactively check for those. Only exceptions you know may happen, but you can't do anything about. Beyond that, for the sake of your data's state, let it crash.

If you are swallowing exceptions, it generally means you don't understand your program or why you are getting an exception. Catching System.Exception is the poster child of code smells...

jlembke
  • 13,217
  • 11
  • 42
  • 56
  • 2
    exactly, if your application is throwing exception, try and learn why that exception is being thrown in the first place, then place checks (ie. if file exists) to prevent them. – Jon Erickson Feb 03 '09 at 00:48
  • If the "#1 priority is to never crash" then this is nice in theory but it doesn't meet the requirements. I'm sure you'd like to argue about the requirements but I suspect that the OP doesn't have this as an option (if he did, he would have already explained this to his customer ;-) – jdigital Feb 03 '09 at 01:32
  • @jdigital - agreed. That is a good point. His question does specify "never crash" – jlembke Feb 05 '09 at 21:48
  • @jdigital - True, but leaving your app in an inconsistent state may be worse than crashing. Some combination of lambda calculus and thorough unit testing might be a more fruitful approach. – Ishmael Feb 27 '09 at 22:04
  • I've seen worse: a method that caught `Exception` at one indent level, then caught `Exception` about 5 more times in nested code inside the initial `catch`. I guess they wanted to be *really* sure their code wouldn't crash. – Mike Spross Apr 27 '10 at 05:35
8

Actually, I very rarely use a catch block except for logging purposes. finally is much more common for me. Most times, lock or using do everything I can usefully do (and indeed, that is a finally also).

Eric Lippert has a blog entry on exceptions that may be useful.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
4

Generally IMO it is better to put smaller chunks that are out of your control in a try catch. If you say:

try
{
   //anything that could possibly go wrong
   //This kind of thing is only good for Logging IMO and could be done in
   //Global.asax
}

How could you possibly know what to do in your catch method cause it could be anything...

Its much better to go:

try
{
   //divide user imputs
}
catch(DivideByZeroException)
{
  // tell user bad inputs ect....
}
catch (Exception e)
{
    //If you choose to throw the exception you should
    //***********************
    throw; 
    //VS
    throw ex; //Throw ex will restart the stack trace  
    // recover
}
finally
{
    //Clean up resources and continue
}

In which finally is always run

cgreeno
  • 31,943
  • 7
  • 66
  • 87
4

The key to this question is the following line:

// recover

To be able to recover, you have to know what and how to recover. And that's assuming it is possible to recover, which quite frequently it isn't.

You should only use the catch part of try/catch/finally to swallow an exception when you know how to handle the exception, when you know how to recover from it, and when you're sure you can do so without leaving the application in an inconsistent or invalid state.

If you can do this for all possible exceptions in all method calls in your application then go right ahead, otherwise you might need to re-think your #1 priority (sometimes failing fast is a better options than trying to keep an application alive when something has gone wrong, and having a much harder to debug crash later on).

Greg Beech
  • 133,383
  • 43
  • 204
  • 250
2

There is performance overhead for try blocks, if you do that your entire function will run slower then it otherwise would. catch (Exception e) is also a bad idea, if you catch you want to do something useful with what you caught, and if you catch all exceptions it is impossible to know what you should be doing.

Matt Briggs
  • 41,224
  • 16
  • 95
  • 126
2

You can do this, although almost in any given environment you're running in, there's a global exception handler where you can catch and handle even unknown errors.

For web apps, there's the Global.asax, for a console program, just wrap your Main() in a try/catch, for services, there's AppDomain.CurrentDomain.UnhandledException, etc.

You should wrap sections where you can predict what the exception might be in more specific blocks, but the global exception handlers should greatly simplify your code and help you out.

CubanX
  • 5,176
  • 2
  • 29
  • 44
2

You should only catch and stop the exception without rethrowing it if you can meaningfully handle it. Otherwise it is an error and it should propagate up.

I assume that when they say "this app should never crash" there is an implicit requirement that it behaves correctly. Only stoping exceptions that are meaningfully handled satisfies the behaving correctly requirement.

Typically an app will have a single top-level catch block to catch and log unhandled exceptions. These should occur infrequently (and perhaps your requirement can be interpreted to mean these should not happen at all). If you catch and stop exceptions anywhere else in your code, you risk not discovering these problems. If you catch log and stop in lots of other parts of your code, you have a poorly constructed app from the perspective of separation-of-concerns.

Frank Schwieterman
  • 24,142
  • 15
  • 92
  • 130
1

I try to avoid try catch blocks generally. I prefer to use blocks to force the user into obeying the rules of an application. For example, if a user should only enter an int that is equal to or less than an int x I'd use:

if (input > x)
{
     Console.WriteLine("Invalid input. Please enter a number that is equal to or less than x.");
{...}
}

rather than using:

catch (IndexOutOfRangeException)
{
      //error message here
}

From my own personal experience I find it easier to write as you can avoid encapsulating code in a try block (guarding code).

Of course, there will always be times where using try catch is unavoidable - I just like to work around it where possible.

Harry
  • 61
  • 1
  • 15
0

Our current application has a similar mandate: Never crash. Always back out gracefully. To do this, you have to make sure that every line of code is either enclosed in a try-catch block or only called by code that its exceptions can bubble up into.

Also, to protect against uncaught exceptions, we attach an UnhandledExceptionEventHandler to AppDomain.CurrentDomain.

Yes - that Jake.
  • 16,725
  • 14
  • 70
  • 96
  • 1
    I didn't down-vote this, but your statement "you have to make sure that every line of code is either enclosed in a try-catch block..." starts out on the wrong foot. It's the second part of the statement that you have to ensure: that there is always an upstream exception handler. – jdigital Feb 03 '09 at 01:27
  • 1
    This seems like a bad design. From everything I've read you should be using try-catches to handle environment, situations that depend on network (or server) resources, or are out of your control. Thus I will down-vote. – ConfusedDeer Mar 18 '16 at 13:20
-1
public void functionName  
{
  try
  {
     //your codes
     //sometimes 'return' shows exceptions
  }
  catch(Exception e)
  {
    messagebox.show(e.Tostring());   //to know what is the exception
  }
  finally
  {
  }
}
-1

You should use them anytime a piece of code can thrown an exception.

You have to be careful, catching general exceptions is never a good idea. You have to decide which layer you want to handle them.

Meaning the deeper you are you want to catch very specific excpetion and go more general. In a database catch the SqlException. As you go higher in the stack you catch more exceptions to finally catching the general exception at the very top.

That way you can deal with each exception on a case by case basis. A general exception you aren't going to know what to do with.

David Basarab
  • 72,212
  • 42
  • 129
  • 156
  • 2
    *Every* line of code can throw an exception. OutOfMemoryException, ThreadAbortException, etc... And you should only catch it if you can do something useful. Most times, you can't. – Marc Gravell Feb 02 '09 at 23:52
-3

try catch in c#:

try{

}
catch (NullReferenceException en)
{

}
Bo Persson
  • 90,663
  • 31
  • 146
  • 203