Exception Handling

Exceptions are simply errors, typically resulting from syntax, runtime, and logical flaws.

The System.SystemException class serves as the base class of all predefined system exceptions. Review some of its classes below:

Name Description
System.IO.IOException It addresses I/O errors.
System.IndexOutOfRangeEx ception It addresses errors from methods which refer to out of bound array elements.
System.NullReferenceExce ption It addresses errors from null object dereferencing
System.DivideByZeroExcep tion It addresses errors from dividing by zero.
System.InvalidCastExcept ion It addresses errors from incorrect typecasting.
System.OutOfMemoryExcept ion It addresses errors from application memory allocation.

Management of code with the potential to be impacted by an exception is performed using try-catch, try-finally, or try-catch-finally control statements. The try block contains the potentially affected code. The catch block manages exceptions. The finally block contains the default code the statement runs regardless of whether an exception occurs. All try blocks require one or more catch blocks, or a finally block. Omitting necessary elements results in a compiler error. Control statements for exceptions also utilize the throw keyword. Throw statements present the actual error and typically appear within if or catch blocks. All objects thrown must directly or indirectly derive from the System.Exception class. Review syntax for try-catch-finally statements below:

try
{
	//statements
}
catch (AnException ex)
{
	//exception handling statements
}

Only handle exceptions with known handling procedures. Never catch base class System.Exception without rethrowing it at the catch block end.

try
{
	//statements
}
finally
{
	//statements
}
try
{
	//statements
}
catch (AnException ex)
{
	//exception handling statements
}
finally
{
	//statements
}

CATCH

Catch blocks specify the exceptions they catch. The type specification is known as an exception filter. The exception must be derived from the Exception class. Avoid specifying Exception as the filter unless the means of handling all exceptions is known, or a throw statement appears at the end of the catch block. Review two examples of a catch statement below:

int GetInt(int[] array, int index)
{
	try
	{
		return array[index];
	}
	catch(System.IndexOutOfRangeException e)
	{
		throw new System.ArgumentOutOfRangeException(
			"The parameter index is not within range.");
	}
}
static int GetValueFromArray(int[] array, int index)
{
	try
	{
		return array[index];
	}
	catch (System.IndexOutOfRangeException ex)
	{
		System.ArgumentException argEx = new
System.ArgumentException("Index not within range", "index", ex);
		throw argEx;
	}
}

Multiple catch blocks containing different filters can be chained together. Evaluation of these blocks happens top to bottom, however, only a single catch block will execute for each exception thrown. The first block offering the specific type or base class of the exception thrown will execute. If no blocks contain a matching filter, blocks without a filter are executed if present. Always position catch blocks with the most specific (or derived) exception types first.

Exception handling is most appropriate in the scenarios that follow:

  1. The reasons why the exception may be thrown are clear.
  2. It is possible to spawn and throw a new and more specific exception.
  3. An exception must be partially handled before passing it for more processing.

FINALLY

Finally blocks clean actions executed within the try block. After the try block and any associated catch blocks complete, the finally block always executes. The finally block can perform a wide variety of actions which release resources, e.g., database connections, file streams, and graphics handling. The finally block performs these actions without waiting for object finalization from runtime garbage collection.

In the example below, the finally block is employed in closing a file opened by the try block:

System.IO.FileStream file = null;
System.IO.FileInfo fileinfo = new System.IO.FileInfo
("C:\\workingdoc.txt");
try
{
	file = fileinfo.OpenWrite();
	file.WriteByte(0xF);
}
finally
{
	//Inspect for null in case of OpenWrite fail
	if (file != null)
	{
		file.Close();
	}
}

It checks the file handle state prior to closing. In the event that the try block fails to open the file, the file handle retains the null value, and the finally block does not close it. The finally block closes the file on successful opening.

Review an example of a try-catch-finally statement below:

public class XYZClass
{
	void ReadFile(int index)
	{
		string path = @"c:\directory1\subdirec\tester.txt";
		System.IO.StreamReader file = new
System.IO.StreamReader(path);
		char[] buffer = new char[16];
		try
		{
			file.ReadBlock(buffer, index, buffer.Length);
		}
		catch (System.IO.IOException e)
		{
			Console.WriteLine("An error occurred reading from {0}.
Message = {1}", path, e.Message);
		}

		finally
		{
			if (file != null)
			{
				file.Close();
			}
		}
		//handle the buffer
	}
}

USER-DEFINED EXCEPTIONS

All user-defined exceptions must derive from the Exception class:

public class AUserDefinedException: Exception
{
	public AUserDefinedException(string message): base(message)
	{
	}
}

Employ the throw keyword in using user-defined exceptions:

throw (new AUserDefinedException(“Insert error message here.”);