Structured Exception Handling (SEH):
SEH is a technique for dealing with runtime exceptions. Let's go through some terminology first:- Bugs: error made by the programmer
- User errors: error caused by individuals running your application
- Exceptions: runtime anomalies
- unified approach
- can throw SOAP fault to a remote caller
- contains human readable description
- Class type represent the details of the exception
- Member that throws an instance of the exception class to the caller
- Exception-prone member in caller's side
- Catch in caller's side
Consider the important methods and property of Exception class at below. As you see many of the properties are read-only in nature, since derived types will typically supply default values for each property.
public class Exception : ISerializable, _Exception
{
//public constructors
public Exception();
public Exception(string message);
public Exception(string message, Exception innerException);
//public properties
public virtual IDictionary Data { get; }
public virtual string HelpLink { get; set; }
public Exception InnerException { get; }
public virtual string Message { get; }
public virtual string Source { get; set; }
public virtual string StackTrace { get; }
public MethodBase TargetSite { get; }
//public methods
public virtual Exception GetBaseException();
public virtual void GetObjectData(SerializationInfo info, StreamingContext context);
public Type GetType();
}
Note that _Exception interface allows a .NET exception to be processed by an unmanaged code base and the ISerializable interface allows an exception object to be persisted across boundaries.
Here is the description of Exception type properties:
- Data: retrieve a collection of key/value pairs which provides additional programmer defined information about the exception (read only). the collection by default is empty.
- HelpLink: URL to help file or website
- InnerException: it used in order to get information about the previous exception(s) that caused the current exception to occur.(read only)
- Message: returns textual description of a given error.(set as constructor parameter)
- Source: name of the assembly or the object which threw the current exception.
- StackTrace: a string which contains a sequence of calls that triggered the exception. (read only)
- TargetSite: returns a MethodBase object, which describes numerous details about the method that threw the exception.
Non debug mode: (start without debugging)
Unhandled exception(release mode) |
Debug mode:
Unhandled exception(Debug mode) |
try
{
myObject.ThrowExceptionSample();
}
catch (Exception e)
{
Console.WriteLine("Mehod: {0}", e.TargetSite);
Console.WriteLine("Message: {0}", e.Message);
Console.WriteLine("Source: {0}", e.Source);
}
try/catch output |
TargetSite:
TargetSite returns strongly typed System.Reflection.MethodBase object, that contains useful information about the method as well as the class which threw the exception, such as:- MethodBase.DeclaringType: return the fully qualified name of the class
- MethodBase.MemberType: identify the type of member (method / property)
//sample method to send an exception
public void ThrowExceptionSample()
{
//create local variable in order to initialize some properties and methods
Exception ex = new Exception("this method shows how to throw an exception");
ex.HelpLink = "http://mehdicsharpblog.blogspot.com/";
ex.Data.Add("TimeStamp", string.Format("exception occured at {0}",DateTime.Now));
ex.Data.Add("Cause", "Just for demonstration");
throw ex;
}
Here is the try/catch block:
//try/catch block in the caller
try
{
myObject.ThrowExceptionSample();
}
catch (Exception e)
{
Console.WriteLine("Mehod: {0}", e.TargetSite);
Console.WriteLine("Class defining member: {0}", e.TargetSite.DeclaringType);
Console.WriteLine("Member Type: {0}", e.TargetSite.MemberType);
Console.WriteLine("Message: {0}", e.Message);
Console.WriteLine("Source: {0}", e.Source);
Console.WriteLine("Help Link: {0}", e.HelpLink);
if (e.Data != null)
{
Console.WriteLine("Data:");
foreach (DictionaryEntry item in e.Data)
Console.WriteLine("-> {0}: {1}", item.Key, item.Value);
}
}
Exception example output |
- System-Level Exception : exceptions that are thrown by the .NET platform (aka non-recoverable, fatal errors) which are derived from System.SystemException, which in turn derives from System.Exception.
- Application-Level Exception : it is good practice to extend your custom exception from System.ApplicationException to identify code base executing application
It is a good practice to use following exception for incomplete methods as it does Visual Studio on your behalf when you use auto completion features:
throw new NotImplementedException();
Custom Exception:
It is good practice to build a strongly typed exception that represents the unique details of your current problem. Custom exception can be derived directly from System.Exception or from System.ApplicationException. it is always better to mark the exception class as public, cause exceptions are often passed outside of assembly boundaries. As an example we create a exception class for shape class:
[Serializable]
public class ShapeSampleException : ApplicationException
{
public DateTime TimeStamp { get; set; }
public string Cause { get; set; }
//constructors:
//default
public ShapeSampleException() { }
//set the inherited message property
public ShapeSampleException(string msg)
: base(msg) { }
//handel inner exception
public ShapeSampleException(string msg, Exception inner)
: base(msg, inner) { }
public ShapeSampleException(SerializationInfo info, StreamingContext context)
: base(info, context) { }
//custom
public ShapeSampleException(string msg, string cause, DateTime time)
:base(msg)
{
Cause = cause;
TimeStamp = time;
}
}
By adding above custom exception class we our throw exception block become like this:
public void ThrowExceptionSample()
{
ShapeSampleException ex = new ShapeSampleException("this method shows how to throw an exception",
"Just for demonstration", DateTime.Now);
ex.HelpLink = "http://mehdicsharpblog.blogspot.com/";
throw ex;
}
And here is the new try/catch block:try
{
myObject.ThrowExceptionSample();
}
catch (ShapeSampleException e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.TimeStamp);
Console.WriteLine(e.Cause);
}
ShapeSampleException class diagram (inheritance) |
exception snippets template |
[Serializable]
public class MyException : Exception
{
public MyException() { }
public MyException(string message) : base(message) { }
public MyException(string message, Exception inner) : base(message, inner) { }
protected MyException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}
It might occur one try block trigger numerous possible exceptions, in these cases we can use multiple catch block. Exception will proceed by the first match exception, that's why it is always better to start with most specific exception.C# provides a way to handle all errors in very general way by leave the catch block without any parenthesis and arguments.
catch
{
//catch any kind of exception
}
You can rethrow the exception to the caller by throw keyword. Pay attention throw will rethrow the original exception object.
Inner Exceptions:
If you encounter an exception while processing another exception, you need to record the new exception object as an "inner exception" within a new object of the same type as the initial exception, which is only useful when the caller has the ability to gracefully catch the exception in the first place.
catch (ShapeSampleException exception)
{
try
{
//let's say another exception will occur here
}
catch (Exception inner_excpetion)
{
//Throw an exception that records the new exception,
//as well as the message of the first exception
throw new ShapeSampleException(exception.Message, inner_excpetion);
}
}
Finally Block:
In order to see exceptions thrown by a base class library member you may refer to .NET framework 4.0 SDK documentation or simply hovering your mouse cursor over the member name:
exceptions thrown by a base class library |
View Details of Exception |
Corrupted State Exception (CSE):
.NET 4.0 have introduced new name space ExceptionServices under mscorlib as you can see in below snapshot. This namespace helps you to equip various methods within your application with the ability to intercept and process CSE.Object Browser fro Exception Services |
As you know .NET platform sits on top of the hosting operating system. Within the windows API, it is possible to trap extremely low-level errors (CSE).
Before .NET 4.0 the CLR would allow these very low-level OS-specific errors to be trapped using general System.Exception catch block, however .NET platform does not provide much by way of elegant recovery code. Now for .NET 4.0 you need to import the System.Runtime.ExceptionServices namespace and add the [HandledProcessCorruptedStateException] attribute in order to trap low-level OS errors within catch block .
Reference: Pro C# 2010 and the .NET 4 Platform by Andrew Troelsen.
No comments:
Post a Comment