#866 – A catch Block Without Arguments Catches All Exceptions

You typically include an argument in a catch block that indicates the type of exception to catch.

            catch (FileNotFoundException fnfExc)
            {
                Console.WriteLine(string.Format("Hey, we can't find file {0}!",
                                                fnfExc.FileName));
            }

You can also omit the arguments on the catch block entirely.  In this case, the catch block will catch all exceptions, regardless of their type.  Because you don’t declare an exception variable, however, you won’t have access to information about the exception.

            try
            {
                DoSomething();
            }
            catch
            {
                Console.WriteLine("No idea of what happened, but it must be something bad");
            }

Although possible, not specifying the type of exception to catch is not recommended.  Even exceptions originating from outside of CLS-compliant code will be wrapped in an exception whose type derives from Exception.  So you should always specify an exception variable in the catch clause.

Advertisement

#865 – A catch Block Specifies the Type of Exception to Catch

In most cases, a catch block will specify the type of exception to intercept and catch.  Any exception occurring in the associated try block whose type matches the type indicated in the catch block will be caught.  Exceptions whose type is derived from the specified exception type will also be caught.

In the example below, we catch only exceptions of type FileNotFoundException, or of types that derive from this type. Other exception types will not be caught and will continue to bubble up the call stack.

            try
            {
                DoSomething();
                AskUserForFilename();
                DoSomethingElse();
            }
            catch (FileNotFoundException fnfExc)
            {
                Console.WriteLine(string.Format("Hey, we can't find file {0}!", fnfExc.FileName));
            }

#864 – An Example of a finally Block with No catch Block

When an exception occurs while executing code in a try block that has an associated finally block, the code in the finally block will execute before the exception bubbles up the call stack.

Below is an example.  MethodA calls MethodB, which in turn calls MethodC.  MethodC throws an exception.  When this happens, the code in MethodB’s try block is interrupted and the code in the finally block is executed.  The exception then bubbles up the call stack, where it is then caught by the catch block in MethodA.

        private static void MethodA()
        {
            try
            {
                MethodB();
                Console.WriteLine("After MethodB call");
            }
            catch (Exception xx)
            {
                Console.WriteLine("Exception caught in MethodA!");
            }

            Console.WriteLine("Finishing up MethodA");
        }

        private static void MethodB()
        {
            try
            {
                Console.WriteLine("Before MethodC() call");
                MethodC();
                Console.WriteLine("After MethodC() call");
            }
            finally
            {
                Console.WriteLine("MethodB() finally block");
            }

            Console.WriteLine("Finishing up MethodB()");
        }

        private static void MethodC()
        {
            throw new Exception("Uh-oh");
        }

864-001

#863 – How a finally Block Works with No catch Block

When you include a finally block with some code that’s surrounded by a try block, you’re saying that you want the code in the finally block to run after the code in the try block, whether or not an exception occurs.

If no exception occurs while executing the statements in the try block, the statements in the finally block simply execute after the code in the try block.

If an exception does occur and you have a finally block, but no catch block, the following happens:

  • Some of the code in the try block executes, up to the point where the exception occurred
  • The code in the finally block executes
  • The exception continues bubbling up the call stack
  • Code in the current method that’s located after the finally block does not execute

#862 – Options for Including catch and finally Blocks

When you define a try block using the try keyword, you must also do one of the following:

  • Include one or more catch blocks after the try block
  • Include a finally block after the try block
  • Include one or more catch blocks after the try block, followed by a finally block

Whether you include a catch block, a finally block, or both, depends on what you want to accomplish:

  • Include catch blocks to intercept and act upon exceptions that got thrown as a result of executing the code in the try block.
  • Include a finally block if there are things that need to happen (like releasing resources), regardless of whether or not an exception occurs.
  • Include both catch and finally blocks if both statements above are true.

#861 – A finally Block Always Executes

When you use a try block, you’re defining a block of code for which you can catch an exception, using a catch block.  You can also include a finally block, which dictates a block of code that will execute whether or not an exception occurs.

Suppose that you have the following code:

                try
                {
                    Console.WriteLine("BEFORE the call");
                    SomeMethod();
                    Console.WriteLine("AFTER the call");
                }
                catch (Exception exc)
                {
                    Console.WriteLine("Exception caught in catch block");
                }
                finally
                {
                    Console.WriteLine("Code in finally block executing");
                }

If an exception does not occur, all of the code in the try block will execute, followed by all of the code in the finally block.

861-001

 

If the SomeMethod method throws an exception, the code in the try block after the call to SomeMethod will not execute.  Instead, the code in the catch block will execute, followed by the code in the finally block.

861-002

#860 – Exceptions Bubble up the Call Stack

When you define a try/catch block, the handler defined in the catch block will catch exceptions that originate directly from the code in the try block.  But the handler will also catch exceptions that originate in methods called from the code in the try block, or from code that those methods call.  In short, a catch block will catch any exceptions thrown by code that executes as a result of executing the block of code in the try block.  (Assuming that the exception is not caught elsewhere).

In the example below, code within a try block calls SomeMethod, which calls AnotherMethod.  AnotherMethod then calls YetAnother.  If an exception is thrown from the YetAnother method, the exception will bubble up the call stack until an exception handler is found.  In this the handler associated with the try block around the SomeMethod call will catch the exception.

860-001

 

#859 – The Scope of a try Block

A try/catch block consists of:

  • try statement followed by a block of code contained in braces { }
  • One or more catch statements, optionally indicating the type of exception that can be caught

The idea of the try block is to indicate a block of code for which an exception can be caught.  An exception that occurs as a result of calling any of the statements in the try block can be caught in the associated catch block.

In the example below, we catch exceptions that occur in the Dog constructor, the Dog.Bark call, or the Dog.Print call.  An exception thrown from any of these methods, or code that they call, will be caught in the catch block.

                try
                {
                    // Construct a dog
                    Dog d = new Dog("Kirby", 15);

                    // Bark at volume=11
                    d.Bark("Woof", 11);

                    // Print info
                    d.Print();
                }
                catch (Exception exc)
                {
                    Console.WriteLine("Something went wrong.  Message:");
                    Console.WriteLine(exc.Message);
                }

859-001

#858 – Reading Exception Information in a Handler

When you catch an exception in a block of code that serves as an exception handler, you can read information about the error that occurred from an Exception object.  Every exception object will derive from the System.Exception class.  So, at a minimum, you’ll be able to access the properties of System.Exception.  (Not all properties will always contain values, however).

In the example below, the Bark method throws an exception of type System.Exception.  We query the System.Exception instance and dump out some of its values.

                try
                {
                    Dog d = new Dog("Kirby", 15);
                    d.Bark("Woof");
                }
                catch (System.Exception exc)
                {
                    Console.WriteLine(string.Format("Type = {0}", exc.GetType()));    // System.Exception
                    Console.WriteLine(string.Format("Message = {0}", exc.Message));   // Basic message
                    Console.WriteLine(string.Format("Source = {0}", exc.Source));     // Originating assembly
                    Console.WriteLine("Stack:");             // Dump out stack
                    Console.WriteLine(exc.StackTrace);
                }

Note that the call stack shows that Program.Main called Dog.Bark.
858-001

#857 – What an Exception Object Contains

When some code throws an exception, it creates an instance of System.Exception or one of its derived classes and populates the exception object with information that might help understand what went wrong.  The runtime environment also writes some information into the exception object.

In an exception handler, you’ll have access to the information stored within the Exception object.  Listed below are the properties of this type that you can use to get information about the exception.

Always populated:

  • Message – A message summarizing the error
  • StackTrace – A multiline string, describing the current call stack, at the time of the error
  • Source – Name of the assembly where the error originated
  • TargetSite – Information about the method that threw the exception (MethodBase)

Sometimes populated:

  • InnerException – An earlier exception that triggered the current exception  (optional)
  • Data – A series of keyword/value pairs, with additional information about the error  (optional)
  • HelpLink – Link to associated help file  (optional)