# C# Exception Handling

Till now, you have written a lot of codes in C#. But the codes were not yet ready to handle errors. For example, take a case when a user enters a negative value to a factorial program, our code will not throw any error but a negative value is definitely not a valid input for the calculation of factorial and hence, we will get a wrong result. One way to handle this situation would be to use if/else clause but C# provides a different tool specifically to handle errors. So, let’s learn about that.

## Try Catch

We use try and catch to handle errors in C#. The code which we want to execute is written inside try. If the statements inside the try have any error, then the statement inside the catch block is executed. Let’s have a look at some examples.

using System;

class Test
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Hello World");
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
}

Hello World

As you can see that there was no error in the statement inside the try block, so it executed successfully and the statement inside the catch block didn’t execute.

Let’s have an example with some error and see what happens.

using System;

class Test
{
static void Main(string[] args)
{
try
{
int a = 2;
int b = 0;
int c = a/b;

Console.WriteLine(c);
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
}

System.DivideByZeroException: Attempted to divide by zero. at Test.Main (System.String[] args) [0x00004] in <2399e335feaf40b7ab8f8808c37f07ae>:0

There is no syntax error in our code, so our code got executed. Also, there is no error in the first two statements of the try, so they were executed successfully. But we tried to divide a number with 0 and thus, it threw an error which is caught by the next catch block and the codes inside it got executed.

Here, e is the error which was thrown by the try block.

## Finally

When we have codes which we want to get executed in any case i.e., regardless of the execution of try or catch block, we write those codes in the finally block. Let’s look at an example.

using System;

class Test
{
static void Main(string[] args)
{
try
{
int a = 2;
int b = 0;
int c = a/b;

Console.WriteLine(c);
}
catch(Exception e)
{
Console.WriteLine(e);
}
finally
{
Console.WriteLine("Either of try or catch executed");
}
}
}

System.DivideByZeroException: Attempted to divide by zero. at Test.Main (System.String[] args) [0x00004] in <2399e335feaf40b7ab8f8808c37f07ae>:0
Either of try or catch executed
using System;

class Test
{
static void Main(string[] args)
{
try
{
Console.WriteLine("Hello World");
}
catch(Exception e)
{
Console.WriteLine(e);
}
finally
{
Console.WriteLine("Either of try or catch executed");
}
}
}

Hello World
Either of try or catch executed

Let's take one more example in which try block is executed.

## Throw

We can also throw an exception anytime we want using the throw keyword. Let’s see it working.

using System;

class Test
{
static int Divide(int a, int b)
{
return a/b;
}
static void Main(string[] args)
{
int a = 2;
int b = 0;
if(b == 0)
throw new DivideByZeroException("Dividing by 0 not allowed");
else
Console.WriteLine(Divide(a, b));
}
}

System.DivideByZeroException: Dividing by 0 not allowed

## Exceptions in C#

There are many exceptions available in C#. Some of the common exceptions are:

Exception Description
DivideByZeroException Raised when division by 0 is tried
NullReferenceException Raised while refering to null object
FileNotFoundException Raised when the mentioned file is not found at the specified location
IndexOutOfRangeException Raised when the index of an array is outside upper and lower limit.
OutOfMemoryException Raised when the program doesn't have sufficient memory
TimeoutException Raised when the allotted time is out
StackOverflowException Raised when the stack overflows
FieldAccessException Raised when invalid private or protected part is accessed

## Custom Exception

We can also derive the Exception class to create our own custom exceptions. Let's take an example.

using System;

class NegativeNumberNotAllowed: Exception
{
public NegativeNumberNotAllowed(string message): base(message)
{

}
}

class Test
{

static void CheckForNegative(int number)
{
if(number < 0)
{
throw new NegativeNumberNotAllowed("Negative number is not allowed");
}
}

static void Main(string[] args)
{
try
{
CheckForNegative(-10);
}
catch(NegativeNumberNotAllowed e)
{
Console.WriteLine(e);
}
}
}

NegativeNumberNotAllowed: Negative number is not allowed

## Checked and Unchecked

checked and unchecked are two keywords used to handle arithmetic overflow. Think of a case when you are trying to add 1 to the maximum value of an integer i.e., int.MaxValue + 1. Normally, we will get a negative value because int wraps around from MaxValue to MinValue i.e., if it is exceeding the maximum value, it will become the minimum value.

We use checked to throw an error in the case of overflow. So, we will get an error instead of getting the integer to wrapping around the negative value. Let's take an example.

using System;
class Test
{
static void Main(string[] args)
{
checked
{
int x = int.MaxValue + 1;
Console.WriteLine(x);
}
}
}

file.cs(8,19): error CS0220: The operation overflows at compile time in checked mode

unchecked allows the overflow and won't raise any errors.

using System;
class Test
{
static void Main(string[] args)
{
unchecked
{
int x = int.MaxValue + 1;
Console.WriteLine(x);
}
}
}

-2147483648