#915 – An Exception Can Cross Assembly Boundaries

If code within one assembly calls code within another assembly, exceptions originating within the code being called can bubble up to the calling code.  The exception can be thrown from one assembly and caught in another.

Below, code in the ConsoleApplication1 assembly calls code in the DogLibrary assembly (the Dog.Bark method).  When an exception originates in DogLibrary, we can catch it in the code running in ConsoleApplication1.

915-001

Code in ConsoleApplication1:

            try
            {
                Dog d = new Dog("Bowser");
                d.Bark(100);
            }
            catch (ApplicationException exc)
            {
                Console.WriteLine(exc.ToString());
            }

Code in DogLibrary:

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

        public Dog(string name)
        {
            Name = name;
        }

        public void Bark(int numTimes)
        {
            if (numTimes > 10)
                throw new ApplicationException("Too many times to bark");

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

Catching an exception in ConsoleApplication1 that was thrown from DogLibrary:
915-002

#914 – Using the Debugger to Break when an Exception Is Thrown

By default, if you have an exception handler defined, the debugger in Visual Studio will not break (i.e. stop) at the point where an exception is thrown.

You can, however, configure Visual Studio to break at the point when the exception is thrown.  To enable breaking when an exception is thrown, do the following:

  • From the Debug menu, select Exceptions…

914-001

  • Find the specific type of exception for which you want the debugger to break and click on the Thrown column.  You can select an entire class of exceptions, or a specific exception type.  In the example below, we select all Common Language Runtime Exceptions.

914-002

  • Click the OK button

Now, when you run in debug mode, the debugger will display a dialog at the point where an exception is thrown and give you a chance to break (stop).

914-003

 

If you do break, you can then examine the exception object.

914-004

 

#913 – How to Document that a Method Can Throw an Exception

You can use XML Documentation to document the fact that a method can throw an exception.  You use the Exception tag to indicate the type of exception that can be thrown.  You can also provide a comment related to the exception, which will show up in an XML Documentation file that you generate.

        /// <summary>
        /// Print somebody's name
        /// </summary>
        /// <param name="name">Name to be printed</param>
        /// <exception cref="ApplicationException">Will throw exception if name is Mortimer</exception>
        /// <exception cref="JustBecauseException">I throw this exception on Tuesdays</exception>
        static void PrintMyName(string name)
        {
            if (name.ToLower().Equals("mortimer"))
                throw new ApplicationException("I don't like the name Mortimer");

            if (DateTime.Now.DayOfWeek == DayOfWeek.Tuesday)
                throw new JustBecauseException("Tuesday is my day off");

            Console.WriteLine(string.Format("Your name is {0}", name));
        }

Intellisense will now include a list of the exceptions that might be thrown, when displaying the method’s name.
913-001

 

If you generate a XML Documentation file, it will also include this information.

913-002

#912 – Intellisense Can Show Exceptions that a Method Might Throw

In some cases, when the Intellisense function within Visual Studio shows you information about a method that you are going to call, it will also list potential exceptions that the method might throw.

In the example below, we see that the Matrix.Invert method can throw an exception of type InvalidOperationException.

912-001

 

It’s not the case that every single method that you might call in the Base Class Library (BCL) will provide this information.  Some methods will list the exceptions that they might throw, but many will not.

#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

#910 – One Example of a finally Block

You use a finally block when you have logic that should execute whether or not an exception occurs when executing a block of code.

One example of something that you might do in a finally block is to call a Dispose method on an object that implements IDisposable.  You would do this because you want to make sure that you always call Dispose on the disposable object, whether or not an exception occurs when using the object.

(Note: You can achieve the same pattern with the using statement, which automates invocation of a Dispose method).

            StreamWriter sw = new StreamWriter(@"D:\Log.txt");
            try
            {
                sw.Write(string.Format("Did something at {0}", DateTime.Now));
            }
            finally
            {
                sw.Dispose();
            }

#909 – When a finally Block Executes

The purpose of a finally block is to define some code that should always execute, whether or not an exception occurs while executing code in the corresponding try block.

Exactly when a finally block executes depends on several things:

  • If the code in the try block executes without throwing an exception or transferring control elsewhere
    • The finally block executes after the code in the try block
  • If an exception occurs while executing code in the try block ..
    • .. and the exception is caught in a catch block associated with the same try statement — the body of the catch block executes, followed by the body of the finally block
    • .. and the exception is not caught — the body of the finally block executes before the exception propagates back up the call stack
  • If a goto or return statement is encountered in the try block
    • The finally block executes before control is transferred