Skip to main content

Exceptions and Exception handling in C# Explained


Exceptions and Exception handling in C#

The C# language's exception handling features help you deal with any unexpected or exceptional situations that occur when a program is running. Exception handling uses the trycatch, and finally keywords to try actions that may not succeed, to handle failures when you decide that it is reasonable to do so, and to clean up resources afterward. Exceptions can be generated by the common language runtime (CLR), by the .NET Framework or any third-party libraries, or by application code. Exceptions are created by using the throw keyword.
In many cases, an exception may be thrown not by a method that your code has called directly, but by another method further down in the call stack. When this happens, the CLR will unwind the stack, looking for a method with a catch block for the specific exception type, and it will execute the first such catch block that is found. If it finds no appropriate catch block anywhere in the call stack, it will terminate the process and display a message to the user.
C# includes built-in classes for every possible exception. All the exception classes are directly or indirectly derived from the Exception class. There are two main classes for exceptions - SystemException and ApplicationException. SystemException is a base class for all CLR generated errors whereas ApplicationException serves as a base class for all application related exceptions, which you want to raise on business rule violation.
Exception Class Hierachy

Exception classes Hierarchy
As you can see in the above figure, SystemException class is a base class for all the exception that can occurs during execution of the program. No other class derives ApplicationException class by default, because you as a programmer need to derive this class to create your own exeception classes as per the business rules.

Important Exception Classes

The following table lists important exception classes available in .Net.
Exception Description
ArgumentException Raised when a non-null argument that is passed to a method is invalid.
ArgumentNullException Raised when null argument is passed to a method.
ArgumentOutOfRangeException Raised when the value of an argument is outside the range of valid values.
DivideByZeroException Raised when an integer value is divide by zero.
FileNotFoundException Raised when a physical file does not exist at the specified location.
FormatException Raised when a value is not in an appropriate format to be converted from a string by a conversion method such as Parse.
IndexOutOfRangeException Raised when an array index is outside the lower or upper bounds of an array or collection.
InvalidOperationException Raised when a method call is invalid in an object's current state.
InvalidCastException Raised when incompitible types are being converted.
KeyNotFoundException Raised when the specified key for accessing a member in a collection is not exists.
NotSupportedException Raised when a method or operation is not supported.
NullReferenceException Raised when program access members of null object.
OverflowException Raised when an arithmetic, casting, or conversion operation results in an overflow.
OutOfMemoryException Raised when a program does not get enough memory to execute the code.
StackOverflowException Raised when a stack in memory overflows.
TimeoutException The time interval allotted to an operation has expired.
Every exception class in .Net is derived from the base Exception class. It includes the following important properties using which you can use to get information about the exception when you handle the exception.

Property Description
Message Provides details about the cause of the exception.
StackTrace Provides information about where the error occurred.
InnerException Provides information about the series of exceptions that might have occurred.
HelpLink This property can hold the help URL for a particular exception.
Data This property can hold arbitrary data in key-value pairs.
TargetSite Provides the name of the method where this exception was thrown.

When an error occurs, either application code or the default handler handles the exception.

The Anatomy of C# Exceptions

Exceptions allow an application to transfer control from one part of the code to another. When an exception is thrown, the current flow of the code is interrupted and handed back to a parent try catch block. C# exception handling is done with the follow keywords: try, catch, finally, and throw
·         try – A try block is used to encapsulate a region of code. If any code throws an exception within that try block, the exception will be handled by the corresponding catch.
·         catch – When an exception occurs, the Catch block of code is executed. This is where you are able to handle the exception, log it, or ignore it.
·         finally – The finally block allows you to execute certain code if an exception is thrown or not. For example, disposing of an object that must be disposed of.
·         throw – The throw keyword is used to actually create a new exception that is the bubbled up to a try catch finally block.

C# try and catch

The try statement allows you to define a block of code to be tested for errors while it is being executed.
The catch statement allows you to define a block of code to be executed, if an error occurs in the try block.
The try and catch keywords come in pairs:

Syntax

    public static void Main()
    {
        try
        {
            //  Block of code to try
        }
        catch (Exception e)
        {
            //  Block of code to handle errors
        }
     }
Consider the following example, where we create an array of three integers:
The code snippet below will generate an error, because numArray[5] does not exist.

int[] numArray = { 1, 2, 3 };
        Console.WriteLine(numArray[5]); // error!

The error message will be something like shown below:

System.IndexOutOfRangeException: 'Index was outside the bounds of the array.'
If an error occurs, we can use try...catch to catch the error and execute some code to handle it.
In the following example, we use the variable inside the catch block (e) together with the built-in Message property, which outputs a message that describes the exception:
     public static void Main()
    {
        try
        {
            int[] myNumbers = { 1, 2, 3 };
            Console.WriteLine(myNumbers[5]);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

Finally

The finally statement lets you execute code, after try...catch, regardless of the result:
    public static void Main()
    {
        try
        {
            int[] myNumbers = { 1, 2, 3 };
            Console.WriteLine(myNumbers[5]);
        }
        catch (Exception e)
        {
            Console.WriteLine("Something went wrong.");
        }
        finally
        {
            Console.WriteLine("The 'try catch' is finished.");
        }
    }

The throw keyword

The throw statement allows you to create a custom error.
The throw statement is used together with an exception class. There are many exception classes available in C#: ArithmeticExceptionFileNotFoundExceptionIndexOutOfRangeExceptionTimeOutException, etc:
 Example

static void checkAge(int age)
    {
        if (age < 18)
        {
   throw new ArithmeticException("Access denied - You must be at least 18 years old.");
        }
        else
        {
            Console.WriteLine("Access granted - You are old enough!");
        }
    }

Performance considerations

Throwing or handling an exception consumes a significant amount of system resources and execution time. Throw exceptions only to handle truly extraordinary conditions, not to handle predictable events or flow control. For example, in some cases, such as when you're developing a class library, it's reasonable to throw an exception if a method argument is invalid, because you expect your method to be called with valid parameters. An invalid method argument, if it is not the result of a usage error, means that something extraordinary has occurred. Conversely, do not throw an exception if user input is invalid, because you can expect users to occasionally enter invalid data. Instead, provide a retry mechanism so users can enter valid input. Nor should you use exceptions to handle usage errors. Instead, use assertions to identify and correct usage errors.
In addition, do not throw an exception when a return code is sufficient; do not convert a return code to an exception; and do not routinely catch an exception, ignore it, and then continue processing.

Re-throwing an exception

In many cases, an exception handler simply wants to pass the exception on to the caller. This most often occurs in:
·         A class library that in turn wraps calls to methods in the .NET Framework class library or other class libraries.
·         An application or library that encounters a fatal exception. The exception handler can log the exception and then re-throw the exception.
The recommended way to re-throw an exception is to simply use the throw statement in C# without including an expression. This ensures that all call stack information is preserved when the exception is propagated to the caller. The following example illustrates this. A string extension method, FindOccurrences, wraps one or more calls to String.IndexOf(String, Int32) without validating its arguments beforehand.

Example

using System;
using System.Collections.Generic;

public static class Library
{
    public static int[] FindOccurrences(this String s, String f)
    {
        var indexes = new List<int>();
        int currentIndex = 0;
        try
        {
            while (currentIndex >= 0 && currentIndex < s.Length)
            {
                currentIndex = s.IndexOf(f, currentIndex);
                if (currentIndex >= 0)
                {
                    indexes.Add(currentIndex);
                    currentIndex++;
                }
            }
        }
        catch (ArgumentNullException)
        {
            // Perform some action here, such as logging this exception.

            throw;
        }
        return indexes.ToArray();
    }
}

Caller

public class Example
{
    public static void Main()
    {
        String s = "It was a cold day when...";
        int[] indexes = s.FindOccurrences("a");
        ShowOccurrences(s, "a", indexes);
        Console.WriteLine();

        String toFind = null;
        try
        {
            indexes = s.FindOccurrences(toFind);
            ShowOccurrences(s, toFind, indexes);
        }
        catch (ArgumentNullException e)
        {
            Console.WriteLine("An exception ({0}) occurred.",
                              e.GetType().Name);
            Console.WriteLine("Message:\n   {0}\n", e.Message);
            Console.WriteLine("Stack Trace:\n   {0}\n", e.StackTrace);
        }
    }

    private static void ShowOccurrences(String s, String toFind, int[] indexes)
    {
        Console.Write("'{0}' occurs at the following character positions: ",
                      toFind);
        for (int ctr = 0; ctr < indexes.Length; ctr++)
            Console.Write("{0}{1}", indexes[ctr],
                          ctr == indexes.Length - 1 ? "" : ", ");

        Console.WriteLine();
    }
}

A caller then calls FindOccurrences twice. In the second call to FindOccurrences, the caller passes a null as the search string, which cases the String.IndexOf(String, Int32) method to throw an ArgumentNullException exception. This exception is handled by the FindOccurrences method and passed back to the caller. Because the throw statement is used with no expression, the output from the example shows that the call stack is preserved.

References

1.     W3schools
3.     TutorialTeacher
4.     CsharpCorner



Comments

Popular posts from this blog

Classes in C# Explained

C# Class Explained A class is nothing but an encapsulation of properties and methods that are used to represent a real-time entity, as explained by Guru99 . For instance, if you want to work with Guest’s data as in our previous DataDriven Web application . The properties of the Guest would be the Id, GuestName, Address, Phone number etc of the Guest. The methods would include the entry and modification of Guest data. All of these operations can be represented as a class in C# as shown below. using System; namespace CsharpnaijaClassTutorial {     public class Guest     {         public int Id { get ; set ; }         public string GuestName { get ; set ; }         public string Address { get ; set ; }         public string WhomToSee { get ; set ; }     ...

ASP.NET MVC Views

Views in ASP.NET MVC Application explained Find a related article By  Steve Smith  and  Luke Latham from Microsoft Corporation here In the Model-View-Controller (MVC) pattern, the  view  handles the application's data presentation and user interaction. A view is an HTML template with embedded  Razor markup . Razor markup is code that interacts with HTML markup to produce a webpage that's sent to the client. In ASP.NET MVC, views are  .cshtml  files that use the  C# programming language  in Razor markup. Usually, view files are grouped into folders named for each of the application's  controllers . The folders are stored in a  Views  folder at the root of the application as shown: The  Home  controller is represented by a  Home  folder inside the  Views  folder.  The  Home  folder contains the views for the  About ,  Contact , and  Index...

ASP.NET MVC Routing

ASP.NET MVC Routing ASP.NET MVC routing is a pattern matching system that is responsible for mapping incoming browser requests to specified MVC controller actions. When the ASP.NET MVC application launches then the application registers one or more patterns with the framework's route table to tell the routing engine what to do with any requests that matches those patterns. When the routing engine receives a request at runtime, it matches that request's URL against the URL patterns registered with it and gives the response according to a pattern match. Routing pattern is as follows A URL is requested from a browser, the URL is parsed (that is, break into controller and action), the parsed URL is compared to registered route pattern in the framework’s route table, if a route is found, its process and send response to the browser with the required response, otherwise, the HTTP 404 error is send to the browser. Route Properties ASP.NET MVC routes are res...