1. Technology

Exception Handling Tutorial in C#

Don't let your program crash

By

Stacktrace text

When something goes wrong in a C# program, it often generates an exception. It could be something like trying to open a file that's already opened by something else, or an invalid argument to a method, a reference that is null or a dozen other reasons.

Despite that in most of your code you won't have to worry about exceptions. This tutorial explains how you can deal with them when you need to.

  • Never programmed in C# before? Find out about it, Read About C#

Some programming languages like C do not use exception handling and even with those that do like C++, there can be a case for not using them. Google's style guide for C++ says they do not use exception handling code.

Exceptions are quite slow to process, so use them only when you need to. For Instance there's an int.Parse(string) method that you can use to convert a string to an int. If it can't do the conversion, it raisess one of three exceptions:

  • Argument null
  • Format
  • Overflow
However there's also a method int.TryParse that converts a string to an int and returns true or false if it succeeded. No exception handling is needed.

After a while you'll recognize when you'll need to use exception handling code, so let's see what there is when you need it.

Try Catch Finally

You might be familiar with try ... finally ... end which guarantees that if you allocate some resource, say open a file, that your code will hit the finally and then call your resource deallocation or file close call. If you use the using () statement like this: using (var sr = new StreamReader(Filename)) {
...
}

Behind the scenes, the compiler uses a Try Finally and calls Dispose() on sr in the finally block to properly clean up the sr StreamReader object.

Try Finally doesn't use any exception handling, but it's a great way to write code that allocates resources. Note that if you have a return or even an exception inside a try finally block, the finally will still get called. So it can be useful saying for adding logging, status messages etc.

Try .. catch ... looks just like try ... finally. If you think some code might generate an exception then you simply embed it within a try ... catch block.

Let's see a simple example. Here I've taken a console application and added a new reference to System.Windows.Forms. This then lets me add using System.Windows.Forms and allows me to call MessageBox.Show(String). Unusual to have popup windows in a console program but hey it works!

using System;
using System.IO;
using System.Windows.Forms;

namespace ex1
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                using (var sr = new StreamReader("data.csv"))
                {
                     // Do something with file
                }
            }
            catch (Exception e)
            {
                MessageBox.Show ("File failed to open " + e.Message) ;
            }

            finally
            {
                MessageBox.Show ("Program has finished") ;
            }
        }
    }
}

Assuming there is no data.csv file in the same location as your exe this will throw an exception "Could not find file" which comes from the Exception Message property. I always recommend capturing this message property if you can.

After displaying that message it enters the finally block and pops up another Message box with Program has finished which is a bit self-evident but demonstrates that finally gets hit irrespective of an earlier caught exception in the same Try block.

Catching Exceptions

The catch(Exceptiontype e) lets you look for a specific exception type. The System Namespace contains a quite large number of Exception types. Here are the first three from the System.Namespace documentation page.

  • AccessViolationException
  • AggregateException
  • AppDomainUnloadedException

Personally I think the times when you have to catch a particular exception (say an out of memory one) are pretty rare and you can just try to catch any exception. Note you have the option of specifying an Exception variable, so these alternatives all work (I just picked one of the Exception types for an example).

catch (Exception e)...
catch (Exception)...
catch (AccessViolationException e)...
catch (AccessViolationException)...

I prefer the first one, I think you should always catch the exception variable, as you can get the exception message and even a stack trace.

Exception Methods

Catching the Exception variable lets you log it, or even the stack trace and that's not just handy but should always be built in to any non trivial application.

C# also includes a StackTrace class (see StackTrace class documentation), if you want to capture information on how execution reached the present path. Just add using System.Diagnostics and create an instance of StackTrace and call the ToString() Method. Note in Console.WriteLine, ToString() is called implicitly, that's why it's not shown below.

I added these two lines of code at the start of the example, immediately after static void Main(string[] args) {

var stacktrace = new StackTrace();
Console.WriteLine(stacktrace);

and got this:

   at ex1.Program.Main(String[] args)
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean
preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean
preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

Throwing Exceptions

The Throw keyword lets you raise an exception in code. If your Bargles ever splaggered (cromulent words indeed!), you could throw an exception. The String in the Exception constructor call is stored in the Exception message property.

try
{
    throw new Exception("The bargles have splaggered!") ;
}
catch (Exception e)
{
    MessageBox.Show("It stopped because:" + e.Message) ;
}

Rethrowing an Exception

It's possible that you wish to take some action in a local Exception handler but then pass this exception or another one to be caught further up in the calling chain.

Now catch( Exception e) normally cleans up, so there's no more exception. But the word throw by itself in a catch block will re-throw the same exception so it has to be handled by another try catch handler.

try
{
    throw new Exception("The bargles have splaggered!") ;
}
catch (Exception e)
{
    MessageBox.Show("It stopped because:" + e.Message) ;
    throw;
}

If instead of throw, you do throw new exception() then you can cause a different exception to be thrown, like this: try
{
    throw new Exception("The bargles have splaggered!") ;
}
catch (Exception e)
{
    MessageBox.Show("It stopped because:" + e.Message) ;
    throw new Exception("Something wonderful has happened...") ;
}

That should be handled but is uncaught in this program.

And that's exceptions handled!

  1. About.com
  2. Technology
  3. C / C++ / C#
  4. C# / C Sharp
  5. Learn C Sharp
  6. Tutorial for Handling Exceptions in C#

©2014 About.com. All rights reserved.