8/12/11

throw and throw ex

There are some things in life which come back to bite you in the face(haha...) if you do not pay enough attention to them. In my case one such thing was NOT knowing the difference between throw and throw ex when dealing with exceptions in C#(other languages probably do the same). I didnt know that the stack trace was going to be different depending what whether I did a throw or a throw ex and as a result I always ended up looking up in the wrong places whenever there were exceptions deep inside the call stack.Let me give you an example of what I am talking:

Look at the code below. There are three classes Level 1, Level 2, Level 3. Level makes a call to method HelloLevel2()  in Level2 which in turn makes a call to a method HelloLevel3() in Level 3. The method in Level 3 throws an exception.Pay attention to the text in Red.

public partial class Level1 : System.Web.UI.Page
    {        
        protected void Page_Load(object sender, EventArgs e)
        {            
            Level2 objlevel2 = new Level2();
            objlevel2.HelloLevel2();

        }
    }
 public class Level2
    {
        public void HelloLevel2()
        {
            try
            {
                int x = 10;
                Level3 objlevel3 = new Level3();
                objlevel3.HelloLevel3();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }
public class Level3
    {
        public void HelloLevel3()
        {
            try
            {                
                throw new Exception("Oops....Something got messed up here");
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }
    }

If you look at the stack trace, this is how it looks. If you notice the text in Red you will notice that even though the error occured in HelloLevel3() there is no indication of that. This is happening because the method HelloLevel2() is doing a throw ex inside it's catch block instead of doing a  throw



[Exception: Oops....Something got messed up here]
   WebApplication1.Level2.HelloLevel2() in C:\VisualStudioProjects\WebApplication1\WebApplication1\Level2.cs:20
   WebApplication1._Default.Page_Load(Object sender, EventArgs e) in C:\VisualStudioProjects\WebApplication1\WebApplication1\Default.aspx.cs:29
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
   System.Web.UI.Control.OnLoad(EventArgs e) +91
   System.Web.UI.Control.LoadRecursive() +74
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207

Now, as shown below, I have modified the code in HelloLevel2() to as shown below

 public class Level2
    {
        public void HelloLevel2()
        {
            try
            {
                int x = 10;
                Level3 objlevel3 = new Level3();
                objlevel3.HelloLevel3();
            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }

If we run the application,the stack now looks as shown below:

[Exception: Oops....Something got messed up here]
WebApplication1.Level3.HelloLevel3() in C:\VisualStudioProjects\WebApplication1\WebApplication1\Level3.cs:18

WebApplication1.Level2.HelloLevel2() in C:\VisualStudioProjects\WebApplication1\WebApplication1\Level2.cs:20
WebApplication1._Default.Page_Load(Object sender, EventArgs e) in C:\VisualStudioProjects\WebApplication1\WebApplication1\Default.aspx.cs:29
System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
System.Web.UI.Control.OnLoad(EventArgs e) +91
System.Web.UI.Control.LoadRecursive() +74
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207

As you can see it tells you that the exception actually occured in HelloLevel3(). This information is extremely useful and can save hours of troubleshooting in the wrong direction.

Hope this helps! Peace.