The best way to prevent having bugs in your program or app is to avoid handling errors that could occur in your code. If you can avoid them, you won’t have to check for them and handle them when they happen, right?
While that sounds good in theory, it’s not always possible to completely prevent errors from occurring; otherwise you wouldn’t have a program or app at all! When an error does occur and your program can’t recover on its own, how you handle the error will depend on how much information the error provides about what caused it and where the problem occurred.
That is why I have decided to explain 5 simple and useful ways to succeed handle errors or exceptions in C# like a senior developer.
Understand what is error handling
First and foremost, it is necessary to understand what error handling means. The term error handling refers to a software application’s reaction and recovery mechanisms in the event of an error. That is to say, it is a process that involves accurately predicting, detecting, and resolving errors in applications, programs, or communication.
Maintaining a program’s regular execution flow is made easier via error handling. When it comes to error-handling approaches, many applications really encounter a slew of architectural issues.
🧠Remember: Detect and handle, thrown errors are good.
What is Exception Handling in C#?
Error handling in C# is the process of reacting and responding when an exceptional or anomalous situation occurs while executing C# program code.
It is very common for C# programmers to use
try blocks to separate code that may throw an exception ( affected code excerpt). The next step is to use
catch blocks to handle the exception. Error handling in C# usually requires 4 blocks:
- Try (separate and identify the block of code that may return an exception).
- Catch (catch the exception after identifying it)
- Finally (execute a series of statements after catching the exception)
- Throw (send signals manually when an exception has occurred)
C# Exception types
During the programming process of a .NET application, the developer should always run and check in which part of the app runtime exceptions may occur.
There are many common exception types in C#. Every .NET developer should know how they differ and know under what conditions to throw them. I recommend you to analyze this table of the most common C# exception types and compare them before moving on to the error handling best practices tutorial👇
ArgumentException: An argument that is not
nulland is provided to a method is considered to be invalid.
ArgumentNullException: A method receives a
nullparameter when one is supplied to it.
ArgumentOutOfRangeException: One of the arguments has a value that is not within the acceptable range.
DirectoryNotFoundException: A part of the directory path that you provided is invalid.
DivideByZeroException: In a division operation involving integers or decimals, zero is used as the denominator.
DriveNotFoundException: A drive is unavailable, inaccessible or does’t exist.
FileNotFoundException: A file does’t exist.
FormatException: A conversion method such as
Parsewill not be able to extract a value from a string because the value is not in a suitable format.
IndexOutOfRangeException: An array or collection cannot contain an index because it exceeds its capacity.
InvalidOperationException: A call to a method cannot be made when an object is in its current state.
KeyNotFoundException: It was not possible to locate the key that was specified to gain access to a member in a collection.
NotImplementedException: There is no implementation of a method or action.
NotSupportedException: There is a problem with a certain method or procedure (maybe not supported).
ObjectDisposedException: On an object that has its previous location discarded, an operation is carried out.
OverflowException: An overflow occurs as the result of an operation involving arithmetic, casting, or conversion.
PathTooLongException: The maximum length that can be defined for a path or file name has been exceeded.
PlatformNotSupportedException: On this particular platform, the operation in question is not supported.
RankException: A method receives an array that contains the wrong amount of dimensions as an argument.
TimeoutException: An operation that was supposed to take place during a certain time period has expired.
UriFormatException: The Uniform Resource Identifier (URI) that is being used is incorrect.
How to Handle Exceptions in C#?
Always keep trace of the exception stack
throw e; is not a good way to throw a caught exception since C# allows us, simply with
throw;, to throw the exception in a catch block.
This way we would keep track of the stack and get a much better view of the exception.
Let’ check an example:
Including information in an exception is a good practice since it will help in the debugging of the error. If, on the other hand, the goal is to record an exception, then throw should be used to pass the buck to a caller.
Avoiding the use of throw ex
At first look, any developer could believe that
throw ex; is the best way to rethrow an exception after catching it. Yes, it is a simple way to do it, but not the right way to do it. This option is not good because you would lose the stack trace.
Check this example:
We can see in the good way to do it I have simply used
throw. In this way, the original exception stack would be conserved. Otherwise, with
throw ex, it would be overwritten with the line of code where this statement was called.
Avoid using if conditions
You should consider using numerous catch blocks for exception handling if you need to do different actions depending on the kind of exception. A bad practice is to use
This would be a good example:
Even if we are creating numerous catch blocks, it is always suggested to create a catch block that includes the Exception argument as the final catch block. It provides as an auxiliary catch block.
Always analyze the caught errors
If you catch an error, there’s no point in ignoring it and letting it go because you won’t have a chance to fix it or do anything about it.
It is always better, if you know an error might occur, to wrap that code in a try/catch.
Let’ check an example:
As we can see, throwing the error is not a great solution because it might get lost in the console among all the printed stuff. By wrapping it in a try/catch, we can later (in case an error occurs there) create a plan or have a code path on how to handle it.