We as engineers, developers always conscious of what we code and we keep trying to think ways in which the code being written can FAIL. We try to make the code as clean as possible, easy to decipher/debug, concise and the most important it does what the functionality requirements demands the code to do. Despite all of this, we still end up with bug fixing and of course exceptions. How important is exception handling?
What are Exceptions ?
Exception are simply put object instances from System.Exception class. An exception is a indicator see while executing a program. An exception is a response to an exceptional circumstance that arises while a program is running. Exception handling will help in maintaining normal, required code path to be hit even when unexpected outcomes are seen and doesn't result in abrupt exiting or un-desired outcomes.
In other words, these exceptions and the way its handled will provide a way to transfer control from one part of a program to another. Exceptions in C# provide a structured, uniform, and type-safe way of handling both system level and application-level error conditions.
C# exception handling is built upon four keywords: try, catch, finally, and throw.
- try − A try block identifies a block of code for which particular exceptions is activated. It is followed by one or more catch blocks.
- catch − A program catches an exception with an exception handler at the place in a program where you want to handle the problem. The catch keyword indicates the catching of an exception. There can be multiple catch blocks corresponding to exception type used.
- finally − The finally block is used to execute a given set of statements, whether an exception is thrown or not thrown. For example, if you open a file, it must be closed whether an exception is raised or not. This can be used to dispose up any objects if required incase of error.
- throw − A program throws an exception when a problem shows up. This is done using a throw keyword.
How exceptions are handled?
When an exception occurs, the system searches for the nearest catch clause that can handle the exception, as determined by the run-time type of the exception. First, the current method is searched for a lexically enclosing try
statement, and the associated catch
clauses of the try
statement are considered in order. If that fails, the method that called the current method is searched for a lexically enclosing try
statement that encloses the point of the call to the current method. This search continues until a catch
clause is found that can handle the current exception, by naming an exception class that is of the same class, or a base class, of the run-time type of the exception being thrown. Point to be noted is that a catch
clause that doesn't name an exception class can handle any exception.
Once a matching catch
clause is found, the system prepares to transfer control to the first statement of the catch
clause. Before execution of the catch
clause begins, the system first executes, in order, any finally
clauses that were associated with try
statements more nested that than the one that caught the exception.
If it finds no appropriate catch
block anywhere in the call stack, it will terminate the process and display a message to the user.
Phew… There is no end to the type of errors we developers face while working!
Things to Avoid When Throwing Exceptions
The following list identifies practices to avoid when throwing exceptions:
- Don’t use exceptions to change the flow of a program as part of ordinary execution. Use exceptions to report and handle error conditions.
- Exceptions shouldn’t be returned as a return value or parameter instead of being thrown.
- Don’t throw System.Exception, System.SystemException, System.NullReferenceException, or System.IndexOutOfRangeException intentionally from your own source code.
- Don’t create exceptions that can be thrown in debug mode but not release mode. To identify run-time errors during the development phase, use Debug Assert instead.
- Dont add the least specific exception types in the catch blocks. Always have most specific to least specific exception types in the catch block to ensure the correct error is caught and prompted to the end user.
What exactly is stored in exception properties?
The Exception class includes the following properties that help identify the code location, the type, the help file, and the reason for the exception: StackTrace, InnerException, Message, HelpLink, HResult, Source, TargetSite, and Data.
Message : String type that contains the reason for exception. This message should help the developer to understand what is going wrong.
Stacktrace : String type that contains information about the call stack of code being processed. It contains the trace of the method calls, execution path being hit leading upto the exception.
Data : if IDictionary type containing string key with object value type. This can be used to story any additional user defined exception data.
InnerException : System.Exception type, that capture the preceding exception in new exception.
Source: String type that capture the application/object name that caused the error. By default it contains the originating assembly details.
HResult : In32 type represents the HRESULT numerical value often used with COM-interop.
HelpLink : String type that contains link to URL or URN
TargetSite : System.Reflection.Methodbase contains details about the method from where the exception was thrown.
Hope you all found this article useful. I will be posting more things in the couple of weeks. Until then, happy learning
Quick question for the folks reading this article. Is it possible to break out of try catch finally block? Can I add goto to change the regular course of code path being hit in try, catch, finally block? [Ughh! not goto… I can understand your sentiment here :) ] Can I add yield in try, catch, finally block? I want you all to try it out yourself and then post back what you find.