#1,192 – Following the TryParse Pattern

The int.TryParse method does the same thing as the int.Parse method, but without throwing an exception.  Instead, it returns a boolean value indicating whether the method succeeded or not and writes the result to an out parameter.

You might follow the same pattern when writing your own code, providing a method that throws an exception on failure and a TryXxx version of the method that returns a boolean indicating whether the method succeeded.  Below is an example.

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

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

        public bool TryBark(out string barkSound)
        {
            bool success = false;
            barkSound = "";

            if (Age <= 10)
            {
                success = true;
                barkSound = "Woof";
            }

            return success;
        }

        public string Bark()
        {
            string barkSound;

            if (!TryBark(out barkSound))
                throw new Exception("This dog can't bark");
            return barkSound;
        }
    }
Advertisement

#920 – A finally Block Is Not Executed When a Corrupted State Exception Occurs

When a corrupted state exception occurs as a result of executing some code within a try block, code within an associated finally block is not executed.  This is true whether or not you use the HandleProcessCorruptedStateExceptions attribute to indicate that you want to catch corrupted state exceptions.

In the example below, we execute some code that causes an access violation and a corrupted state exception occurs.  We do catch the CSE, but the code within our finally block is never executed.

        [HandleProcessCorruptedStateExceptions]
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Before call to CausesAccessViolation()");
                CausesAccessViolation();
                Console.WriteLine("Before call to CausesAccessViolation()");
            }
            catch (Exception exc)
            {
                Console.WriteLine(string.Format("Hey, I caught an Exception: {0}", exc.ToString()));
            }

            Console.ReadLine();
        }

        static void CausesAccessViolation()
        {
            try
            {
                IntPtr ptr = new IntPtr(123);
                Marshal.StructureToPtr(123, ptr, true);
            }
            finally
            {
                Console.WriteLine("* finally block in CausesAccessViolation() executing");
            }
        }

920-001

#919 – Think Twice about Handling Corrupted State Exceptions

Corrupted State Exceptions are exceptions that indicate that the memory state of the current process is likely corrupt.  These CSEs by default cannot be caught by your code.  This is normally what you want, since you typically don’t want to continue execution when one of these exceptions occurs.  You can, however, use the HandleProcessCorruptedStateExceptions attribute to indicate that you do want to handle CSEs.

Be very careful when handling Corrupted State Exceptions.  When an exception in this category is thrown, there is a good chance that the memory space of your process is corrupt.  Continuing execution may lead to unpredictable behavior and could even cause other data to become corrupt.

If you do catch Corrupted State Exceptions, you should execute as little code as possible and exit your application as soon as possible.  You might, for example, just log the fact that the CSE occurred and then exit.

#918 – Catching Corrupted State Exceptions

Corrupted State Exceptions are exceptions that indicate that the memory state of the current process is likely corrupt.  These CSEs by default cannot be caught by your code.  This is normally what you want, since you typically don’t want to continue execution when one of these exceptions occurs.

You can, however, set an attribute on a method indicating that you do want to catch Corrupted State Exceptions.  If you set the HandleProcessCorruptedStateExceptions attribute on a method, it will then be able to catch this category of exceptions.

In the example below, we are able to catch the access violation exception.

        [HandleProcessCorruptedStateExceptions]
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Before call to CausesAccessViolation()");
                CausesAccessViolation();
                Console.WriteLine("Before call to CausesAccessViolation()");
            }
            catch (Exception exc)
            {
                Console.WriteLine(string.Format("Hey, I caught an Exception: {0}", exc.ToString()));
            }

            Console.ReadLine();
        }

        static void CausesAccessViolation()
        {
            IntPtr ptr = new IntPtr(123);
            Marshal.StructureToPtr(123, ptr, true);
        }

918-001

#917 – Corrupted State Exceptions Are Not Normally Caught

Starting with .NET 4.0, there are a class of exceptions that will not be caught within a general catch block that catches all exceptions deriving from System.Exception.  By default, a corrupted state exception will not be caught as a System.Exception.  A corrupted state exception is a type of exception, like an access violation, that likely results in the internal state of the process being corrupt.

In the example below, we artificially generate an access violation.  Note that the exception that is raised is not caught, but treated as an unhandled exception.  (Our catch block never executes).

        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("Before call to CausesAccessViolation()");
                CausesAccessViolation();
                Console.WriteLine("Before call to CausesAccessViolation()");
            }
            catch (Exception exc)
            {
                Console.WriteLine(string.Format("Hey, I caught an Exception: {0}", exc.ToString()));
            }

            Console.ReadLine();
        }

        static void CausesAccessViolation()
        {
            IntPtr ptr = new IntPtr(123);
            Marshal.StructureToPtr(123, ptr, true);
        }

917-001

#916 – Exception Can Cross .NET Language Boundaries

An exception being thrown from one assembly can be caught in a different assembly.  This is true even when the assemblies are authored in different .NET languages.

Below, code in the ConsoleApplication2 assembly, which is written in Visual Basic, calls code in the DogLibrary assembly (the Dog.Bark method), which is written in C#.  When an exception originates in DogLibrarywe can catch it in the code running in ConsoleApplication2.

916-001

Assume that the code in DogLibrary looks like:

        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");
        }

And the code in ConsoleApplication2 looks like:

    Sub Main()
        Try
            Dim d As Dog = New Dog("Bowser")
            d.Bark(100)

        Catch ex As Exception
            Console.WriteLine(String.Format("Uh-oh! {0}", ex.ToString()))
        End Try
    End Sub

We can catch the exception in the VB code that was thrown by the C# code.
916-002

#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.