Exception Handling in C#

In this article, we will discuss Exception handling in C# with examples. The process of handling an exception that occurred while a program was being run is known as exception handling. Exception handling is the most important concept in C#. Exception handling in C# is a way to identify and address run-time faults in code and is supported by the try-catch and finally block. Common exceptions have built-in classes in the .NET framework. The exceptions are abnormalities that take place while a program is being run. They may result from the system, logical, or user faults. The .NET runtime environment offers a default mechanism that ends program execution if a user does not provide a way to address certain abnormalities. A technique for handling errors that might occur while a program is being executed is exception handling, To ensure that the program flow is maintained even when there is a runtime issue, exception handling is utilized. The objects that are thrown when a runtime error occurs are called exceptions. C# will generate an exception message and end the program if the exceptions are not handled.



Try/catch in C#:


The try keyword creates a block in which we must write the statements that cause the exception and their related statements. Therefore, the try block must contain the exception-causing instructions as well as any related statements that should not be executed when an exception occurs. The CLR will generate an instance of the Exception class based on the logical error when an exception occurs, and it will then throw that instance, which will be handled by the relevant catch block. Any code that can potentially cause exceptions should be enclosed in a try block. If an exception occurs while the code is being executed, the control flow shifts to the first catch block that matches the exception.

The exception that is thrown from the try block's equivalent catch block is caught by the catch block. It has the logic to deal with the caught exception by taking the appropriate action. It does not accept return types, regular modifiers, or accessibility modifiers. It only accepts a single parameter of type Exception or any of the parent Exception class's subclasses. Any statement that is permissible in .NET can be written inside the catch block, including statements that raise exceptions. In this situation, we can halt the program's abnormal termination and provide the user with an intelligible error notice so they can take the appropriate step to fix the problem. We can have multiple catch blocks for a single try block .

Given below is a syntax of a try-catch block.


Simple try-catch block example:


Syntax:


try

{

// Do something

}


catch

{

// Do something

}



Below is an example of a try-catch block to get the proper usage and idea by the following code.

Example:


 namespace ExceptionHandlingDemo

 {

 internalclassProgram

    {

 staticvoidMain(string[] args)

        {

 try

            {

 int x = 100;

 int y = 50; // suppose if we will put the value of y = 0; then we will get exception.

 int z = x / y;

 Console.WriteLine("The result is :" + z);

    }


 catch(DivideByZeroException ex)

     {

 Console.WriteLine(ex.Message);

     }


 Console.ReadLine();

      }

    }

 }




Output:


 The result is: 2




Multiple catch blocks in single try block:


In C#, you can combine the try block with more than one catch block. In most cases, using several catch blocks to handle various exception types simply implies that each catch block is used to handle a different exception type. Because C# does not permit the use of multiple catch blocks for the same type of exception, if you attempt to use more than one catch block for the same type of exception, you will receive a compile-time error. The try block always comes before the catch block.

Given below is a syntax of multiple catch block

syntax:


try {

  // Do something

 

  }

 

  // 1st catch block

  catch(Exception_Name) {

 

  // Do something

 

  }

 

  // 2nd catch block

  catch(Exception_Name) {

 

  // Do something

 

  }

 


To see how the multiple catch block should be used and what it does, for better implementation see the example below.

Example:


 using System;


 namespace ExceptionHandlingDemo


 {

    internal class Program

    {

        static void Main(string[] args)

        {

            try

            {

                int x = 100;

                int y = 50; // suppose if we will put the value of y = 0; then we will get exception.

                int z = x / y;

                Console.WriteLine("The result is:"+ z);

                string name = null;

                Console.WriteLine(name.Length);

                int[] arr = new int[3];

                arr[0] = 10;

                arr[1] = 20;

                arr[2] = 30;

                arr[3] = 40;

            }


            // Catch block 1

 

            // This Catch block is for

            // handling DivideByZeroException

            catch (DivideByZeroException ex)

            {

                Console.WriteLine(ex.Message);

            }


            // Catch block 2

 

            // This Catch block is for

            // handling IndexOutOfRangeException

            catch (NullReferenceException ex)

            {

                Console.WriteLine(ex.Message);

            }


            catch(Exception ex)

            {

                Console.WriteLine(ex.Message);

            }


            Console.ReadLine();

        }

    }


 }




Output:

null_reference-ex.png


After an exception, the program output will be like this.


 The
result is:2


 Object
reference not set to an instance of an object.





Difference between try and catch block:


  • A block of code can be designated to be checked for errors as it is being performed using the try statement. Whereas if an error occurs in the try block, you may specify a block of code to be run by using the catch statement.


  • To contain a section of code, use a try block. If any code within the try block throws an exception, the exception will be handled by the associated catch. Whereas the Catch block of code is run when an exception occurs. You have the option to handle, log, or ignore the exception at this point.


  • Any code that can potentially cause exceptions should be enclosed in a try block. If an exception occurs while the code is being executed, the control flow shifts to the first catch block that matches the exception. Whereas an exception handler block called a catch block allows you to handle exceptions by logging and auditing them, for example. The catch block accepts an exception-type parameter that can be used to retrieve an exception's details.



Throw keyword in C#:


The throw is a keyword in the C# programming language that can be used to manually throw an exception during a program. Depending on the situation, we can handle these manually thrown exceptions using try-catch blocks. Throw only causes exceptions that are descended from the Exception base class to be raised. The process of generating and signaling the error is referred to as throwing an exception. This is done using the throw keyword followed by a new instance of a class deriving from System.Exception.

Given below is an example of a throw keyword.

Example:


 using
System;


 using
System.Linq.Expressions;


 namespace
ExceptionHandlingDemo


 {

    internal class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Enter your age");

            int age = int.Parse(Console.ReadLine());

             

            if (age > 18)

            {

                Console.WriteLine("congrats! you are eligible for vote");

            }

            else

            {

                throw new Exception("you are not eligible for vote");

            }


            Console.ReadLine();

        }

    }


 }




Output:

throw_exception.png


After an exception, the program out will be like this.


 Enter
your age


 18


 Unhandled
exception. System.Exception: you are not eligible for vote





Raise Exception deliberately in C# code:


The throw keyword can be used to manually raise an exception. The throw keyword can be used to raise any kind of exception that is derived from the Exception class. the original error stack information is preserved if the "throw" statement is used. Rethrowing the previous exception is another name for "throw" with an empty parameter in exception handling. Whereas the stack trace of the exception will be replaced by a stack trace starting at the re-throw point if the "throw ex" statement is used. It is employed to purposefully conceal stack trace data.

Here is the full scenario between throw and throw ex keyword.


throwex_pic.png


Given below is an example of the throw.


Example:


using System;

using System.Linq.Expressions;

namespace ExceptionHandlingDemo

{

    internal class Program

    {

        static void Main(string[] args)

        {

            try

            {

                GetStateName();

                       

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex.Message);

                Console.WriteLine(ex.StackTrace);

               

            }

            Console.ReadLine();

        }

        public static void GetStateName()

        {

            Console.WriteLine("Enter the pincode");

            int pincode = int.Parse(Console.ReadLine());

            try

            {

                if (pincode.ToString().Length > 6)

                    throw new InvalidOperationException("Invalid Pincode for Country India");

               

            }

            catch (System.Exception ex)

            {

                throw ;

            }

        }

    }

}


Note: The throw is used to maintain a complete stack trace of the error from where it originated whenever we use throw.


Output:

throw_ex.png


Enter the pincode

432156789

Invalid Pincode for Country India

   at ExceptionHandlingDemo.Program.GetStateName() in E:\Github\contentBlog\ExceptionHandlingDemo\EceptionHandlingDemo\Program.cs:line 194

   at ExceptionHandlingDemo.Program.Main(String[] args) in E:\Github\contentBlog\ExceptionHandlingDemo\EceptionHandlingDemo\Program.cs:line 18



As we can see the above mentioned output after executed the Program.cs in line number 194 the GetStateName() function threw up an exception then it sent to static void main() function which is in line number 18, so we can see we get complete stack trace of our error while using throw keyword. In simple words we can say Throw maintains the error stack trace.


Now let’s see the example program of throw ex .

Example:


using System;

using System.Linq.Expressions;

namespace ExceptionHandlingDemo

{

    internal class Program

    {

       

        static void Main(string[] args)

        {


         try

            {

                GetStateName();

                       

            }

            catch (Exception ex)

            {

                Console.WriteLine(ex.Message);

                Console.WriteLine(ex.StackTrace);

               

            }


            Console.ReadLine();

        }



        public static void GetStateName()

        {

            Console.WriteLine("Enter the pincode");

            int pincode = int.Parse(Console.ReadLine());


            try

            {

                if (pincode.ToString().Length > 6)

                    throw new InvalidOperationException("Invalid Pincode for Country India");

               

            }

            catch (System.Exception ex)

            {

                throw ex ;

            }


        }

    }

}



Note: The throw ex resets the whole stack trace.


Output:

throw.png



Enter the pincode

1234567890

Invalid Pincode for Country India

   at ExceptionHandlingDemo.Program.GetStateName() in E:\Github\contentBlog\EceptionHandlingDemo\EceptionHandlingDemo\Program.cs:line 197

   at ExceptionHandlingDemo.Program.Main(String[] args) in E:\Github\contentBlog\EceptionHandlingDemo\EceptionHandlingDemo\Program.cs:line 18



The above-mentioned output as we can see after execution the Program.cs in line number 197 the GetStateName() function threw up an exception which resets the error stack trace wherever we used throw ex in the program, it means doesn’t show the exact line of code from where the exception originated and then it sent to main() method function which is in line number 18, Simply we can say the Throw ex is used to resets error stack trace.



Difference between throw and throw ex in C#:


  • Throw is used to throw current exception. Whereas throw ex is used to create a wrapper of exception.


  • Throw does not reset the stack trace and you will get information about the original exception. Whereas throw ex will reset your stack trace so the error will appear from the line where throw ex is written.


  • The original error stack information is preserved if the "throw" statement is used. Rethrowing the previous exception is another name for "throw" with an empty parameter in exception handling. Whereas the stack trace of the exception will be replaced by a stack trace starting at the re-throw point if the "throw ex" statement is used. It is employed to purposefully conceal stack trace data.


  • Throw ex will change the stack trace, whereas throw will preserve the whole stack trace.


  • The throw is used to maintain a complete stack trace of the error from where it originated whenever we use throw. Whereas throw ex resets the stack trace.




Finally block in C#:


The creation of a block by the keyword finally ensures that all statements within it are executed without fail, regardless of whether an exception has happened or not. In other words, whether an exception is thrown or not, whether the thrown exception is handled by the catch block or not, the statements that are placed in the finally block will always be performed. Regardless of whether an exception is raised or not, the finally block will always be executed. To release resources, such as to close any stream or file objects or close database connections that were opened in the try block, a finally block is typically utilized. The finally block is always executed, and depending on whether the program finds an exception or not, it may be executed immediately following the trying block or following the catch block.

Given below is a syntax of a finally block.

Syntax:


finally

{

// Do something

}



Given below is an example of finally block.

Example:


protected void Page_Loader(object sender, EventArgs e)

     {

            if (!IsPostBack)

            {

                //Create the connection object

                SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["ShoppingZone"].ConnectionString); ;

                try

                {

                    // Pass the connection to the command object, so the command object knows on which

                    // connection to execute the command

                    SqlCommand cmd = new SqlCommand("Select * from employee", connection);

                    // Open the connection. Otherwise you get a runtime error. An open connection is

                    // required to execute the command

                    connection.Open();

                    GridView1.DataSource = cmd.ExecuteReader();

                   

                }

                catch (Exception ex)

                {

                   // Handle Exceptions, if any

                }

                finally

                {

                    // The finally block is guarenteed to execute even if there is an exception.

                    //  This ensures connections are always properly closed.

                    connection.Close();

                }

            }

        }





Exception types in C#:


The problem that occurs during program execution is known as an exception, and these exceptions are responses to unusual circumstances that occur during program execution, such as the exception raised whenever we try to divide by zero. Exceptions are used to transfer control from one part of the program to another, and in C#, the handling of exceptions is managed by four keywords: try, catch, finally, and throw blocks.

There are different types of exceptions in C#, let’s look at some them mentioned below.



System.OutOfMemoryException:


This exception handles failures that result from not having enough free memory. Given below is an example of the System.OutOfMemoryExceptions.


Example:



using System;

namespace ExceptionHandlingDemo

{

    internal class Program

    {

        static void Main(string[] args)

        {


// a string variable is created and tried to store 2.1 billion characters and this causes an out of memory exception.

            string val = new string('r', int.MaxValue);

            Console.ReadLine();

        }

    }

}




Output:


Exception of type 'System.OutOfMemoryException' was thrown.

ExceptionHandlingDemo.dll!ExceptionHandlingDemo.Program.Main(string[] args) Line 10  C#





System.NullReferenceException:


This exception deals with the errors that result from referencing a null object. Consider the below example program to demonstrate System. NullReferenceException.


Example:



using System;

namespace ExceptionHandlingDemo

{

    internal class Program

    {

        static void Main(string[] args)

        {

            //a string variable is defined, and it is referencing to null

            string name = null;

            //the length of the value referencing to null is checked if it is equal to zero causing an exception

            if (name.Length == 0)

            {


Console.WriteLine(name);

         
}

            Console.ReadLine();

        }

    }

}




Output:


 Object reference not set to an instance of an object.


 ExceptionHandlingDemo
.dll!ExceptionHandlingDemo.Program.Main(string[] args) Line 13  C#




System.InvalidCastException:


This exception deals with the typecasting-related errors that are produced. Given below is an example of the System. InvalidCastException.


Example:


using System;     

namespace ExceptionHandlingDemo


{

    internal class Program

    {

        static void Main(string[] args)

        {

            Console.WriteLine("Enter a number");

            string number = Console.ReadLine();

 

        // implicit casting to explicit casting conversion where data format different

        int num = int.Parse(number); 

       Console.WriteLine("Number is : " + number);     

  Console.ReadLine();

        }

    }


}



Output:


Input string was not in a correct format.

ExceptionHandlingDemo.dll!ExceptionHandlingDemo.Program.Main(string[] args) Line 15  C#




System.ArrayTypeMismatchException:


This exception deals with the errors that are caused by a type mismatch with the array type. Consider the below example program to demonstrate System. ArrayTypeMismatchException.


Example:

using System;

namespace EceptionHandlingDemo

{

    internal class Program

    {

        static void Main(string[] args)

        {

         

            // a string is defined and assigned the values which is then assigned to object class array and then an integer is tried to put in the same array which causes an exception

            string[] arr1 = { "Welcome", "to", "CSharp" };

            object[] arr2 = arr1;

             arr2[0] = 5;

            Console.WriteLine(arr1[2]);

            Console.ReadLine();

        }

    }

}



Output:


Attempted to access an element as a type incompatible with the array.

ExceptionHandlingDemo.dll!ExceptionHandlingDemo.Program.Main(string[] args) Line 16 C#




System.IndexOutOfRangeException:


This exception handles the errors that occur when a method refers to an array that is beyond its valid range. Given below is an example of the System. IndexOutOfRangeException.


Example:

using System;

namespace EceptionHandlingDemo

{

    internal class Program

    {

        static void Main(string[] args)

        {


// an array is defined to store 3 integers but then an integer is tried to be stores at a position outside of the size of the array which causes an exception

           

         int[] arr = new int[3];

            arr[0] = 10;

            arr[1] = 20;

            arr[2] = 30;

            arr[3] = 40;


            foreach(int i in arr)

            {

                Console.WriteLine(i);

            }


            Console.ReadLine();

        }

    }

}




Output:


Index was outside the bounds of the array.

ExceptionHandlingDemo.dll!ExceptionHandlingDemo.Program.Main(string[] args) Line 15 C#




System.DivideByZeroException:


The errors that are generated when a dividend is divided by zero are handled by this exception. Consider the below example program to demonstrate System. DivideByZeroException.


Example:


using System;

namespace EceptionHandlingDemo

{

    internal class Program

    {

        static void Main(string[] args)

        {

           //an integer variable res is defined which is tried to divide by zero which causes an exception

            int res = 10 / int.Parse("0");

            Console.WriteLine(res);

            Console.ReadLine();

        }

    }

}




Output:


Attempted to divide by zero.

ExceptionHandlingDemo.dll!ExceptionHandlingDemo.Program.Main(string[] args) Line 12 C#




Conclusion:


Whenever you suspect an error could occur for any reason, you should utilize an exception handler. You must employ a catch statement and work your way up from a general to a specific exception. Without an appropriate exception handler, your entire piece of software or code is at risk. It will be difficult for you or any user to track down the issue in the source code and correct it if you do not place the portion of code that you believe could raise an exception in the future inside the try-catch block. If this happens, your program may terminate abnormally.

Hope you enjoyed reading this article and found it useful. Please share your thoughts and recommendations in the comment section below.


Share This Post

Linkedin
Fb Share
Twitter Share
Reddit Share

Support Me

Buy Me A Coffee