#911 – finally Block Execution When Exception Is Rethrown

Recall that if an exception is caught in a catch block, an associated finally block will execute after the execution of the catch block.

If the catch block rethrows the exception, the finally block will execute after the catch block, but before the exception propagates back up the call stack.

In the example below, the sequence is:

  • Exception thrown from try block in HelperMethod
  • Exception caught in catch block in HelperMethodcatch block executes up to throw
  • finally block in HelperMethod executes
  • Exception caught in catch block of Main method
        static void Main(string[] args)
        {
            try
            {
                HelperMethod();
            }
            catch
            {
                Console.WriteLine("Caught exception in Main()");
            }

            Console.ReadLine();
        }

        static void HelperMethod()
        {
            try
            {
                throw new ApplicationException("Uh-oh");
            }
            catch
            {
                Console.WriteLine("In catch block, before re-throwing");
                throw;
            }
            finally
            {
                Console.WriteLine("In finally block");
            }
        }

911-001

Advertisements

#901 – Throwing a New Exception from a catch Block

Within a catch block, you can rethrow the original exception using the throw statement.  This allows any method further up in the call stack to also handle the exception.

There are also cases when you want to throw an exception that is different from the exception that you just caught.  You can do this using the throw new syntax and by storing the original exception in the new exception’s InnerException property.

In the example below, the code in the DoDogStuff method catches a DogBarkException, handles it, and then throws a new (more general) exception.

        static void Main(string[] args)
        {
            try
            {
                DoDogStuff();
            }
            catch (Exception xx)
            {
                Console.WriteLine("** Exception in Main():");
                Console.WriteLine(xx.ToString());
            }
        }

        static void DoDogStuff()
        {
            try
            {
                Dog d = new Dog("Kirby", 15);
                d.Bark(BarkSound.Woof, 99);
            }
            catch (DogBarkException xx)
            {
                Console.WriteLine(string.Format("** DogBarkException: Can't bark {0} times!", xx.NumTimes));
                throw new ApplicationException("Failure to do dog stuff", xx);
            }
        }

901-001

#883 – Re-throwing an Exception

When you catch an exception in an exception handler, you have the option of executing some code and then re-throwing the exception.  When you re-throw an exception from a handler, code that called the current method has the option of also handling the exception.  Alternatively, if no higher-level handler exists, the exception will be treated as an unhandled exception after you re-throw it.

In the example below, DoSomeStuff catches all exceptions, writes information to a log file and then re-throws the exception.

        private const string MyLogFile = "App1.log";

        static void Main(string[] args)
        {
            Console.WriteLine("About to do some stuff");

            try
            {
                DoSomeStuff();
            }
            catch (Exception xx)
            {
                Console.WriteLine(xx.ToString());
            }

            Console.ReadLine();
        }

        static void DoSomeStuff()
        {
            try
            {
                Dog d1 = new Dog("Jack", 15);
                Dog d2 = new Dog("Kirby", 150);
            }
            catch (Exception xx)
            {
                StreamWriter sw = new StreamWriter(MyLogFile, true);  // append
                sw.WriteLine(string.Format("Exception at {0}", DateTime.Now));
                sw.WriteLine(xx.ToString());
                sw.Close();

                throw;  // Re-throw
            }
        }

883-001

#881 – When to Throw Exceptions

Your code should throw an exception when

  • Something has gone wrong and your code cannot execute normally
  • You catch an exception and want to add some additional information
  • You catch an exception and your application cannot gracefully recover from the problem

Some examples of when you might throw an exception:

  • Parameter value that is out of range passed to a function
  • Parameter values that are inconsistent passed to a function
  • Invalid values passed to function (e.g. username with wrong password)
  • Function called while application is in the wrong state 

Do not throw exceptions

  • As part of normal operation, to control program flow
  • To return data back to code that called a function
  • Just to indicate which function was executing when an exception was caught

#873 – Full Example of Throwing and Catching an Exception

Below is a complete example of throwing an exception from a method and catching/handling that exception further up the call stack.

Code for Dog class that throws an exception if we ask a dog to bark too many times:

    public class Dog
    {
        public string Name { get; set; }
        public int Age { get; set; }

        // Dog constructor
        public Dog(string name, int age)
        {
            Name = name;
            Age = age;
        }

        // Dog.Bark
        public void Bark(int numTimes)
        {
            if (numTimes > 10)
                throw new ArgumentException(
                    string.Format("{0} is just too many times to bark", numTimes));

            for (int i = 1; i <= numTimes; i++)
                Console.WriteLine("Woof");
        }
    }

Code that calls the Bark method, with an exception handler in the Main() method:

        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Before MethodA call");
                MethodA();
                Console.WriteLine("After MethodA call");
            }
            catch (Exception xx)
            {
                Console.WriteLine(
                    string.Format("Caught in Main(): {0}",
                                  xx.Message));
            }

            Console.ReadLine();
        }

        private static void MethodA()
        {
            Console.WriteLine("Before MethodB call");
            MethodB();
            Console.WriteLine("After MethodB call");
        }

        private static void MethodB()
        {
            Dog d = new Dog("Kirby", 15);
            d.Bark(99);
            Console.WriteLine("I barked 99 times");
        }

Below is the output.
873-001

#872 – Code After a throw Statement Is Not Executed

When you throw an exception using the throw statement, control transfers immediately to the calling function.  No additional statements in the method containing the throw statement are executed.

In the example below, if you call the Bark method and pass in a value for numTimes that is greater than 10, an exception is thrown.  In this case, the for loop will never execute–i.e. the dog won’t bark.

        // Dog.Bark
        public void Bark(int numTimes)
        {
            if (numTimes > 10)
                throw new ArgumentException(
                    string.Format("{0} is just too many times to bark", numTimes));

            for (int i = 1; i <= numTimes; i++)
                Console.WriteLine("Woof");
        }

#856 – Choosing an Exception Type to Throw

When you throw an exception, you create and populate an instance of the System.Exception class, or one of its derived classes.

While it’s possible to throw an exception of type System.Exception, it’s not normally recommended.  You typically want to throw as specific an exception as possible, for two reasons:

  • To provide some specific details about what went wrong (e.g. filename that could not be found, rather than just a general message).
  • To allow an exception handler to catch specific types of exceptions

Typically, when throwing an exception, you do one of the following:

  • Throw an exception whose type matches one of the predefined exception types in the .NET Framework.  (E.g. System.ArgumentException)
  • Throw an instance of System.ApplicationException and provide a relevant message
  • Define your own custom exception type, which inherits from System.Exception, and throw an instance of that type.