[C#] Exception Handling

Handling errors and exceptions in a structured way is one of the main features of progamming languages. All OOP languages provide the way to throw and catch exceptions and the “try/catch” is the common construct of C-based languages.

 

1. System.Exception

In OOP, everything is an object. “Exception” is not an exception either. All exceptions are objects in .NET and the “System.Exception” class is the master base class of all exception types.

The “Exception” class provides the following properties:

  • public virtual string Message { get; }
  • public virtual string Source { get; set; } // the name of the application
  • public MethodBase TargetSite { get; } // the method information
  • public virtual string StackTrace { get; } // call stack
  • public virtual string HelpLink { get; set; } // a link to the help file or a help page
  • public Exception InnerException { get; } // the “Exception” instance that caused the current exception
  • public virtual IDictionary Data { get; } // collection of key/value pairs that provide additional user-defined information

The Constructors are:

  • public Exception()
  • public Exception(string message)
  • public Exception(string message, Exception innerException)
  • protected Exception(SerializationInfo info, StreamingContext context) // with serialized data

Note that the “TargetSite” property returns a “System.Reflection.MethodBase” object rather than a plain string.

try
{
  int x = 10;
  int y = 0;
  int result = 0;

  if (y != 0)
    result = x / y;
  else
  {
    Exception e = new Exception("Divide by Zero");
    e.HelpLink = "http://microsoft.com ";
    e.Data.Add("Calculation", string.Format("{0}/{1}", x, y));
    throw e;
  }
}
catch (Exception e)
{
  StringBuilder sb = new StringBuilder();
  sb.AppendLine("Message: " + e.Message);
  sb.AppendLine("Calculation: " + e.Data["Calculation"]);
  sb.AppendLine("Source: " + e.Source);
  sb.AppendLine("Method: " + e.TargetSite.Name);
  sb.AppendLine("Source: " + e.HelpLink);
  sb.AppendLine("StackTrace: " + e.StackTrace);
  Console.WriteLine(sb.ToString());
}

 

2. Throwing Exceptions

The first step of exception handling mechanism is to throw an exception using the “throw” keyword.

Thrown exceptions will bubble up until they are caught in the “try/catch” block.

throw new Exception("Error");

 

3. Handling Exceptions

C# provides the structured way to handle the exceptions: try, catch, and finally

try { }
catch (...) { }
catch (...) { }
finally { }

I think I do not need to explain how the “try/catch/finally” construct works. Just do not forget the order of catch blocks DOES matter! A more specific exception should be caught before a more general exception.

 

4. SystemException and ApplicationException

There are 2 general exception types that derive directly from the “Exception” class.

  • System.SystemException: represents predefined system exceptions
  • System.ApplicationException: represents a non-fatal application exception

The “SystemException” is a catch-all exception type for CLR-related exceptions. Meanwhile, the “ApplicationException” is used as a base class of custom exceptions.

 

5. Custom Exceptions

Rather than using the general “Exception” class for the application-specific errors, you can created a strongly typed exception.

  • Derives from “ApplicationException
  • Mark with the [System.Serializable] attribute
  • Defines a default constructor
  • Defines a constructor that sets the “Message” property
  • Defines a constructor to handle “inner exceptions”
  • Defines a constructor to handle the serialization of your type (protected)
using System.Runtime.Serialization;

[Serializable]
public class DivideByZeroException : ApplicationException
{
  public DivideByZeroException()
    : this ("DivideByZero", null)  { }
  public DivideByZeroException(string message)
    : this(message, null) { }
  public DivideByZeroException(string message, Exception innerException)
    :base(message, innerException) { }
  protected DivideByZeroException(SerializationInfo info,
    StreamingContext context)
    :base(info, context) { }
}

 

6. Catch All Statement

C# supports a “general” catch block that does not explicitly specify the exception type and catches all exception objects.

try { }
catch { }

It is not a good practice to catch all exceptions in this way but it is quite useful when you just need to provide the general handling logic such as logging to the Windows Event.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s