C# Exception Handling
As mentioned above, exceptions disrupt the flow of the program and terminate the program abnormally. It's the developer's responsibility to handle exceptions gracefully. If these errors are not handled properly, the program might crash and you may never know the root cause of failure.
Handling or responding to exceptions is called Exception Handling.
In C#, exception handling is achieved using 4 keywords :
try: code that might generate exceptions is put inside the
try
block.catch: This block
'catches'
the exception generated insidetry
block. The developer could decide what's need done once an exception is generated i.e. logging the stack trace, logging error messages, showing error prompts to the user etc.finally: This code block when written will always execute no matter whether an exception is raised or not. This is useful in scenarios where some clean-up code is required for example closing a file.
throw:
throw
keyword is used to generate new exceptions in code.
In C#, exceptions are a type represented by classes derived from class Exception.
Exception classes
C# .NET includes built-in exception classes for every possible error. The Exception class is the base class of all the exception classes.
below is a list of common C# exception classes :
System.NullReferenceException
β Very common exception related to calling a method on a null object reference.System.IndexOutOfRangeException
β Occurs attempting to access an array element that does not exist.System.IO.IOException
β Used around many file I/O type operations.System.NET.WebException
β Commonly thrown around any errors performing HTTP calls.System.Data.SqlClient.SqlException
β Various types of SQL Server exceptions.System.StackOverflowException
β If a method calls itself recursively, you may get this exception.System.OutOfMemoryException
β If your app runs out of memory.System.InvalidCastException
β If you try to cast an object to a type that it canβt be cast to.System.InvalidOperationException
β Common generic exception in a lot of libraries.System.ObjectDisposedException
β Trying to use an object that has already been disposed of.
Handling exception
try {
int num = 0;
// code that may raise an exception
int divideByZero = 7 / num;
}
catch (Exception e){
// 'catching' and 'handling' the exception
Console.WriteLine("Exception has occurred :" + e.Message);
}
running the above program shows the below output
if finally block is also available then it also gets executed
try {
int num = 0;
// code that may raise an exception
int divideByZero = 7 / num;
}
catch (Exception e){
// 'catching' and 'handling' the exception
Console.WriteLine("Exception has occurred :" + e.Message);
}
finally {
Console.WriteLine("Inside finally");
}
How exception handling workflow works
When an exception is thrown within a try statement, the CLR performs a test:
Does the try statement have any compatible catch blocks?
β’ If so, execution jumps to the compatible catch block, followed by the finally block (if present), and then execution continues normally.
β’ If not, execution jumps directly to the finally block (if present), then the CLR looks up the call stack for other try blocks; if found, it repeats the test.
If no function in the call stack takes responsibility for the exception, the program terminates.
Multiple Catch Blocks
A program code that is written inside a try
block might raise multiple types of exceptions. These multiple types of exceptions could be handled using multiple catch blocks. Remember that a more specialized catch block should come before a generalized one. Otherwise, the compiler will show a compilation error.
class Test {
static void Main(string[] args) {
try {
byte b = byte.Parse(args[0]);
Console.WriteLine(b);
}
catch (IndexOutOfRangeException) {
Console.WriteLine("Please provide at least one argument");
}
catch (FormatException) {
Console.WriteLine("That's not a number!");
}
catch (OverflowException) {
Console.WriteLine("You've given me more than a byte!");
}
}
}
Catching all exception types
a catch
block without bracket or having type as Exception
can handle all exception types.
try{
div = 100 / x;
Console.WriteLine("Not executed line");
}
catch {
Console.WriteLine("oException");
}
Throwing an Exception
using throw
keyword, an exception could be thrown programmatically.
public class ProgramLog {
FileStream logFile = null!;
public void OpenLog(FileInfo fileName, FileMode mode) { }
public void WriteLog() {
if (!logFile.CanWrite) {
throw new InvalidOperationException("Logfile cannot be read-only");
}
// Else write data to the log and return.
}
}
User-defined exceptions
a user-defined exception class can be created by deriving from the Exception
class.
When creating your own exceptions, end the class name of the user-defined exception with the word "Exception", and implement the three common constructors, shown below code :
using System;
public class EmployeeListNotFoundException : Exception {
public EmployeeListNotFoundException() {
}
public EmployeeListNotFoundException(string message)
: base(message) {
}
public EmployeeListNotFoundException(string message, Exception inner)
: base(message, inner) {
}
}
That's it for this article, please share your feedback in the comments.
References and further reading
Subscribe to my newsletter
Read articles from Deepak Kumar Jain directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by