Exception Handling (7), C# Exception Handling Statements

Exception handling is required in any application. It is a very interesting issue where different apps have various way(s) to handle that. I plan to write a series of articles to discuss this issue

respectively.

This article will discuss C# Exception Handling Statements: try-catch-finally and throw keywords.

Introduction

The Exception Handling Statements are

  • throw
  • try-catch
  • try-finally
  • try-catch-finally

Since the first article of my series on Exception Handling, I have mentioned try-catch-finally as one of the methods. However, we did not discuss them in detail because everybody knows them. In this article, we will not discuss the exception statements in general but discuss some features we might miss.

  • A - Valid Formats for try-catch-finally Statements
  • B - The case: try is not handled by catch
  • C - Difference between throw and throw ex

Note:

We will use the code introduced in Exception Handling (1), in ASP.NET MVC, especially using Step 3 - Error handling by Try-Catch, index5.

A - Valid Formats for try-catch-finally Statements

We are very familiar with try-catch-finally Statements, so I will give a short definition:

  • The try statement identifies a block of statements within which an exception might be thrown.
  • The catch statement must be associated with a try statement and identifies a block of statements that can handle a particular exception type. The statements are executed if an exception of a particular type occurs within the try block.
  • The finally statement must be associated with a try statement and identifies a block of statements that are executed regardless of whether or not an error occurs within the try block.

We realize that the catch or finally statement must be associated with a try. Therefore we have the following valid formats for the try-catch-finally Statements will be:

  • try-catch
  • try-finally
  • try-catch-finally

While in the following examples, they are not valid:

Using try only, it will not be compilable with the error message: Expect catch or finally:

Catch only: Syntax error, 'try' expected.

The same is true for finally:

B - The case: try is not handled by catch

As we know, every try must be associated with at least a catch or finally statement, 

  • In the case of try-finally, without a catch, the try will go to the finally for sure, however, 
  • In the case of try-catch(-finally), if the catch does not fit the exception type, the exception will not be caught, the workflow likes this, and the catch is skipped.

C - The Difference between throw and throw ex

The conclusion is obvious:

Throw preserves the stack trace. So let's say Source1 throws Error1, Source2 catches it, and Source2 says throw, then Source1 Error + Source2 Error will be available in the stack trace.

Throw ex does not preserve the stack trace. So all errors of Source1 will be wiped out, and only Source2 errors will be sent to the client.

Let us demonstrate this. Add one more action in ErrorHandlingController: index6

        public ActionResult Index6()
        {
            try
            {
                    ThrowException2(); // line 101
            }
            catch (Exception ex)
            {
                var model = new HandleErrorInfo(ex, "Controller", "Action");
                return new ViewResult()
                    {
                        ViewName = "Error3",
                        ViewData = new ViewDataDictionary(model)
                    };
            }
            return View();
        }

        private static void ThrowException1()
        {
            try
            {
                DivByZero(); 
            }
            catch
            {
                throw; // line 123
            }
        }
        private static void ThrowException2()
        {
            try
            {
                DivByZero(); 
            }
            catch (Exception ex)
            {
                throw ex; // line 134
            }
        }

        private static void DivByZero()
        {
            int x = 0;
            int y = 1 / x; // line 141
        }

For throw:

At Line 101 below, change the function to ThrowException1(),

The workflow: 

  • Line 101 calls method ThrowException1 at Line 115, then
  • Method DivByZero() calls Line 138, then
  • Line 141 introduces an error, then
  • Line 121 catches the error and throw

We can catch the exceptions from Line 103. They are

where

  • Line 141, original exception --- it is preserved
  • Line 123, throw --- re-throw the exception without ex
  • Line 101, the position to call

For throw ex:

At Line 101 below, change the function to ThrowException2(),

The workflow: 

  • Line 101 calls method ThrowException1 at Line 126, then
  • Method DivByZero() calls Line 138, then
  • Line 141 introduces an error, then
  • Line 134 catches the error and throw ex

We can catch the exceptions from Line 103. They are

where

  • Line 134, throw ex --- rethrow the exception
  • Line 101, the position to call

Obviously, the original exception at Line 141 is not preserved. 

We can catch the exception from Error3.cshtml, 

Update the code in Error3.cshtml:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Error</title>
</head>
<body>
    <hgroup>
        <h1>Error 3.</h1>
        <h2>An error occurred while processing your request.</h2>
    </hgroup>

    @model System.Web.Mvc.HandleErrorInfo

    @if (Model != null)
    {   
        <div>
                @Model.Exception.Message
        </div>
        <br />
        <div>
                @Model.Exception.StackTrace
        </div>    
    }
    </body>
</html>

For throw

For throw ex:

References


Similar Articles