Sonali Gagate
Let us now look at the mechanism provided in C# (actually in all the
languages supported by .NET Framework) for error handling through exceptions.
While .NET framework was being designed, one of the main goals was to do much
better error handling than what is available in the traditional programming
model. Towards this aim, the framework through CLR provides the mechanism of
memory management and garbage collection, which helps in avoiding many a common
errors which used to arise in the conventional programming model due to bad or
incomplete programming. Second important goal of the framework was to make it
possible to catch as many errors at compile time (certain errors that can not be
avoided) as possible, which is achieved by having a strongly typed system.
But certain errors can only be caught at run time for which the Framework
provides consistent means of dealing with errors through exceptions.
Exceptions
Exceptions are unexpected conditions arising in normal flow of a code path.
That is, a condition or situation which is not handled in the normal code path.
Many at times we come across these conditions and the function where these
situations are arising is not capable of determining the reason behind them. For
example, if a function is unable to read certain memory location, or unable to
open a file, it can not possibly determine the reason behind that. It could be
because of something that is being done in the calling function before call to
this particular function. This is a typical scenario where exception handling
can be used. In fact, exception handling is designed with situations like this
in mind.
Here is how exception handling works —
One method determines that an exception condition has been reached and
happens not to be in the correct context to deal with the error. It signals to
the runtime that an error has occurred. The runtime traverses back up the call
stack until it finds a method that can properly deal with the error condition.
There are 4 key words in Framework (and consequently in C#) for exception
handling -
try, catch, throw, and finally.
Throwing an exception
When a method detects an exceptional situation and needs to notify the
calling method that an error has occurred, it uses the throw
keyword. When we want to throw an exception, we need to throw an object of type System.Exception
or a derived class of System.Exception.
The syntax is as follows —
Public void CalledFunction() { ... // error occurred throw new Exception(); }
Catching an exception
When an exception occurs (and is thrown by the called method), the calling
method (that has enough context for error handling) catches it using the catch
keyword. The catch keyword defines a block of code, which
is known as "exception handler".
To catch an exception, we need to bracket the code we want to execute in a try
block and then specify which types of exceptions the code within that try
block is capable of handling in a catch block. All the
statements in the try block are processed as usual unless
an exception is thrown by one of the methods being called. If that happens,
control is passed to the first line of the appropriate catch
block - the block that is defined as catching the type of exception that is
thrown.
public void CallingFunction() { try { // Code that we want to execute ... } catch(System.Exception e) { // Handle the errors ... } }
Rethrowing
There can be times, when a method (say method B) has done everything that it
can to handle an error that has occurred, but it still needs to send it back to
its calling function (say method A) for further handling or this error. But for
this, method B needs to be called on Rethrow.
The following code will make this clearer —
public void MethodA() { Rethrow rethrow = new Rethrow(); try { rethrow.MethodB(); } catch(Exception e) { Console.WriteLine(e.Message); } } public void MethodB() { try { // Some code that we want to execute } catch(Exception) { // Handle error at this level first throw; } }
Cleaning up with "Finally"
Many a times, there are certain things you want done, no matter whether your
code has succeeded or you have encountered errors — Closing an opened file,
for example.
So even with error handling and all, we still need a way of making sure
certain code lines are always executed. And this can be done using the keyword
"finally".
public class myExceptionSample { public void ThrowException() { throw new Exception(); } public static void Main() { try { // Code that we want to execute ... ThrowExcption(); } catch(Exception e) { // Error handling } finally { // Final cleanup } } }
Using System. Exception
SystemException is the base class for many of the exception classes in C#.
Since each catch block can handle only one type of exception, the reason behind
multiple derived exception classes is so that we can handle multiple different
exceptions in our code.
There are different constructors for the System.Exception class. And here are
the examples —
public Exception (); // default constructor public Exception(String); protected Exception(SerializationInfo, StreamingContext); public Exception(String, Exception); You can define your own exception classes and you can derive your exception class from SystemException. Here is how you would catch different types of exceptions — try { MethodA(); // Can throw MethodAException. MethodB(); // Can throw MethodBException. } catch(MethodAException e) { // Handle the error. } catch(MethodBException e) { // Handle the error. } catch(Exception e) { // handle default exception }
Note that, the block to handle the default exception has to be the last one.
If you have any other exception block after the default one, that one will never
be called.