To understand exceptions we need to know two
basic things:
-
A failure has occured and throws an
exception by packing the valid information.
-
The exception
is caught is by an Exception Handler.
Below is a simple Example, which shows what
happens when an Exception is not handled:
class ExceptionsEx
{
//001:
Start the Program Execution.
public void StartProgram()
{
Console.WriteLine("Making
Call to F1() " );
F1();
Console.WriteLine("Successfully
returned from F1() " );
}
//002:
Set of Function that calls each other
public void F1()
{
Console.WriteLine("Making
Call to F2() " );
throw new System.Exception();
F2();
Console.WriteLine("Successfully
returned from F2() " );
}
public void F2()
{
Console.WriteLine("Inside
F2 " );
}
//Client
001: Program Entry
[STAThread]
static void Main(string[]
args)
{
//Create
the Object and start the Execution
ExceptionsEx app = new ExceptionsEx();
app.StartProgram();
}
}
In the above code look at the function F1 that
throws an Exception. But, there is no handler to deal with the thrown
exception. This situation is called an Un-Handled exception
situation. When you execute the code you get an un-handled exception
dialog.
The above dialog is shown in debug mode, so
you may get a chance to break the execution to see where the exception is
thrown (or) continue ignoring the exception (Not advisable).
In release mode you will get Un-Handled
Exception in the form of Application crash.
So, how do we avoid Un-Handled Exception?
Simple, Handle it.
2. Handling an Exception
To handle the exception we need to place the
code within a try block. When an exception occurrs inside the try block, the
control looks for the catch block and the exception is handled in the catch
block. Below is the simple skeleton for the try and catch block:
try
{
//Some
Code that may expected to raise an exception
}
catch
{
//Raised
exception Handled here
}
In the above skeleton any exception is
handled. But, the main disadvantage is we don't know what exception is
raised and who raised the exception. Below is the example that handles the
Exception raised by the function F1 and avoids the Crash:
class ExceptionsEx
{
//001:
Start the Program Execution.
public void StartProgram()
{
Console.WriteLine("Making
Call to F1() " );
try
{
F1();
}
catch
{
Console.WriteLine("Some
Exception Occurred. I don't know what Exception it is and where it Occured.
Sorry!");
}
Console.WriteLine("Successfully
returned from F1() " );
}
//002:
Set of Function that calls each other
public void F1()
{
Console.WriteLine("Making
Call to F2() " );
throw new System.Exception();
Console.WriteLine("Successfully
returned from F2() " );
}
//Client 001:
Program Entry
[STAThread]
static void Main(string[]
args)
{
//Create
the Object and start the Execution
ExceptionsEx app = new ExceptionsEx();
app.StartProgram();
}
}
3. Exception Bubbling
In the above example we saw that Exception is
handled in the catch block. But, the function call order is simple (Call
Stack) that is; StartProgram calls the function F1 and F1 raised
exception is handled in the catch block of the StartProgram.
Imagine the situation that happens if there
are multiple nested function calls, and an exception occurrs in the fourth
or fifth nested call. Look at the Picture below:
F1() : Calls F2 within the try block
and handles the exception in catch block.
F2() : Makes a Call to the Function F3. But
it neither wraps the call for F3 in the try block nor has the exception
handler.
F3() : Raises an Exception.
Note, when the exception is thrown by the
function F3, even though the caller is F2, as there is no catch handler the
execution comes out of F2 and enters the catch block of F1. Traveling back
from F3->F2->F1 is known as Stack Unwind. An exception that
occurred in F3 is handled in F1 even when there is no handler at F2; this is
known as Exception Bubbling.
Below is the Example that demonstrates the
Exception Bubbling
using System;
namespace ExceptionHandling
{
class ExceptionsEx
{
//001:
Start the Program Execution.
public void StartProgram()
{
Console.WriteLine("Making
Call to F1() " );
try
{
F1();
}
catch
{
Console.WriteLine("Some
Exception Occurred. I don't know what Exception it is and where it Occured.
Sorry!");
}
Console.WriteLine("Successfully
returned from F1() " );
}
//002:
Set of Function that calls each other
public void F1()
{
Console.WriteLine("Making
Call to F2() " );
F2();
Console.WriteLine("Successfully
returned from F2() " );
}
public void F2()
{
Console.WriteLine("Making
Call to F2() " );
F3();
Console.WriteLine("Successfully
returned from F2() " );
}
public void F3()
{
Console.WriteLine("Inside
F3 " );
throw new System.Exception();
}
//Client
001: Program Entry
[STAThread]
static void Main(string[]
args)
{
//Create
the Object and start the Execution
ExceptionsEx
app = new ExceptionsEx();
app.StartProgram();
}
}
}