Thursday, February 21, 2013

Tips and Tricks of Exception Handling in .Net - Part 2


This is the continuation of my article Tips and Tricks of Exception Handling in .Net - Part 1


Constrained Execution Regions:  Usually, we write code to recover from an exception in catch block. Now what if the catch block itself throws an exception?

Well, you can say that we can use another try/catch block inside our catch. But are you sure you properly recovered from the corrupted state or you are just ignoring it and going forward. This all depends on the actual implementation though, we should always try our level best to keep our application in proper state. In other words, the application should never-ever contain a corrupted state. The CLR provides CER to handle such a situation.

The CER allows you to compile all the code written in your catch and finally block prior to the try block. Hence, if there is any chance of failure in catch block, that happens immediately there by not letting your application with the corrupted state. Here is a sample code describing it from the book CLR via C#.
        public static void Test()
        {
            // Force the code in the finally to be eagerly prepared
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
                Console.WriteLine("In try");
            }
            finally
            {
                // MyType's static constructor is implicitly called in here
                MyType.Foo();
            }
        }

        public class MyType
        {
            static MyType()
            {
                Console.WriteLine("MyType Constructor Called");
            }

            // This attribute is required for PrepareConstrainedRegions to work.
            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
            public static void Foo() { }
        }
If you execute this code you will get the following output:
MyType Constructor Called
In try
As you can see in the output, finally block is compiled prior to the try block there by executing the MyType's static constructor first. All we need to do is call RuntimeHelpers's PrepareConstrainedRegions method prior to try block and apply ReliabilityContract attribute to the methods which needs to be compiled in prior.

Refer this link for more information.

Automatic Generation of try/finally: Ensuring that cleanup code always executes is so important that many programming languages offer constructs that make writing cleanup code easier. For example, the C# language automatically emits try/finally blocks whenever you use the lock, using, and foreach statements. The C# compiler also emits try/finally blocks whenever you override a class’s destructor (the Finalize method). When using these constructs, the compiler puts the code you’ve written inside the try block and automatically puts the cleanup code inside the finally block. Specifically,
  • When you use the lock statement, the lock is released inside a finally block.
  • When you use the using statement, the object has its Dispose method called inside a finally block.
  • When you use the foreach statement, the IEnumerator object has its Dispose method called inside a finally block.
  • When you define a destructor method, the base class’s Finalize method is called inside a finally block.
These are the words of Jeffry Richter(from the book CLR via C#). There is another interesting point which he did not mentioned in the book, but I found it in this stackoverflow question. Here pb noticed that iterator block generates try-fault block instead of  try-finally. 

Now what is this try-fault? can we use it in C#?
       The answer is given in the same SO question by Steve Steiner. In his words, a Finally block always executes on frame exit. A fault block executes only if an exception is unwound past the frame.. That means, the fault block executes only if there is an exception. Now again, another question comes into mind i.e.

If fault block executes only if there any exception in the try block, then whats the difference between fault and catch?
      While researching about this, I got this SO link. Here, the accepted answer says this:
catch - I need to do something with the exception object when an exception occurs.
fault - I don't need the exception object, but I need to do something when an exception occurs.
finally - I don't need the exception object, but I need to do something before the end of the function.

Here is another interesting article regarding this.

Before ending this section, there is another thing which I need to mention. That is about exception filter - Now what is this new concept again? well, here is the answer from previously linked SO post:

It is similar to a catch block but can run arbitrary code to determine whether it wants to handle the error, rather than just matching on type. This block has access to the exception object, and has the same effect on the exception stack trace as a catch block.

Oh! I forgot about the question, can we use fault in c#? You may already got the answer, if not here is it.
        Currently, no languages provide support for fault. However, Bart De Smet shown a way to use it in c# here (You can also produce it using reflection as shown in MSDN, but this is a big pain). The c# also doesn't support filter handler but VB.Net supports it.


Topics will be covered in Part - 3:  FailFast method and CSE(Corrupted State Exceptions).

Read Part - 3

No comments:

Post a Comment