Array Collections File String Windows VB.NET Algorithm ASP.NET Cast Class Compression Convert Data Delegate Directive Enum Exception If Interface Keyword LINQ Loop Method .NET Number Regex Sort StringBuilder Struct Switch Time Value

Things go wrong in computer programs. But if you check for every possible error at every step, your program soon becomes very complex. Exception handling in the C# language isolates these checks in a separate part of your program. It simplifies control flow. It renders programs robust and easy to maintain.
Exceptions in C# provide a structured, uniform, and type-safe way of handling both system-level and application-level error conditions. Hejlsberg et al., p. 599
In the C# language, you can throw exceptions with a throw statement. Just as important, exceptions can be thrown automatically by the runtime because of the values of the variables in your code. In this program we divide by zero. This results in a DivideByZeroException, which is reported.
Overview: These examples cover C# exception types in depth. They also cover try and catch statements.
Program that throws an exception [C#]
using System;
class Program
{
static void Main()
{
try
{
int value = 1 / int.Parse("0");
Console.WriteLine(value);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
Output
Attempted to divide by zero.
Next, we see examples of some of the exception type's properties in the C# programming language. These properties include HelpLink, Message, Source, StackTrace, and TargetSite. This program creates an exception by dividing by zero. Then, it catches the exception instance and writes five properties to the Console.
Program that shows exception properties [C#]
using System;
class Program
{
static void Main()
{
try
{
int value = 1 / int.Parse("0");
}
catch (Exception ex)
{
Console.WriteLine("HelpLink = {0}", ex.HelpLink);
Console.WriteLine("Message = {0}", ex.Message);
Console.WriteLine("Source = {0}", ex.Source);
Console.WriteLine("StackTrace = {0}", ex.StackTrace);
Console.WriteLine("TargetSite = {0}", ex.TargetSite);
}
}
}
Output
(StackTrace was abbreviated for display.)
HelpLink =
Message = Attempted to divide by zero.
Source = ConsoleApplication1
StackTrace = at Program.Main() in C:\...\Program.cs:line 9
TargetSite = Void Main()HelpLink. The HelpLink here is empty because it was not defined on the exception; the Message is a short description of the exception's cause; the Source is the application name; the StackTrace is the path through the compiled program's method hierarchy that the exception was generated from; and the TargetSite is the name of the method where the error occurred.
TargetSite. The TargetSite property is one of the most important ones here. If you simply need to know what method an error occurred in, as is often the case with short programs, this property can be used to simplify what part of the errors you record.
It is possible to store structured data on an exception that is thrown in one part of your program, and then later read in this data. Using the Data dictionary on the Exception instance, you can store associative keys and values.
Program that uses Data property [C#]
using System;
using System.Collections;
class Program
{
static void Main()
{
try
{
// Create new exception.
var ex = new DivideByZeroException("Message");
// Set the data dictionary.
ex.Data["Time"] = DateTime.Now;
ex.Data["Flag"] = true;
// Throw it!
throw ex;
}
catch (Exception ex)
{
// Display the exception's data dictionary.
foreach (DictionaryEntry pair in ex.Data)
{
Console.WriteLine("{0} = {1}", pair.Key, pair.Value);
}
}
}
}
Output
Time = 6/21/2010 11:17:41 AM
Flag = TrueOverview. In this example, we employ the alternative control structure of exception handling in the try/catch blocks. In the try block, a new exception is allocated. Next, the Data property is assigned to. It can be used as a Hashtable or Dictionary. The keys and values are represented by the object type, which means any value or class instance can be used. Finally, the exception instance is thrown and in the catch block we display the Data contents.

Analysis. The usefulness of the Data property on the Exception type largely depends on the complexity of your program. If you have a simple program, it probably won't be useful. But when you have a complex system with a lot of different logical dependencies, you can record important information in the Data storage and then use it later to diagnose problems.

We describe the keywords you need to use to add exception handling control to your programs. The main topics include how to throw, catch, and use finally constructs.
Try Catch Finally Throw
The C# language provides the checked and unchecked contexts that you can use to specify whether exceptions are caused when value types overflow. This can result in more reliable code in some cases, as we point out.
Checked UncheckedThere are many different derived exception types in the .NET Framework. Here, we look at various exception types and demonstrate how they are caused and what you can do to prevent them from occurring.
ArgumentException
ArgumentNullException
ArgumentOutOfRangeException
ArrayTypeMismatchException
DirectoryNotFoundException
DivideByZeroException
FileNotFoundException
FormatException
IndexOutOfRangeException
InvalidCastException
InvalidOperationException
KeyNotFoundException
NotImplementedException
NullReferenceException
OutOfMemoryException
OverflowException
StackOverflowException
TypeInitializationExceptionNote: There are several specific types of database exceptions that you may encounter, including SqlException, SqlCeException, and OdbcException. More information about SQL database usage is available in the Data category.

To test how fast exception handling is, we benchmark a method that uses try/catch against a method that carefully tests for null to avoid failures. Both methods—GetA and GetB—return the first array element if the array is not null.
Program that shows exceptions [C#]
using System;
class Program
{
static void Main()
{
int[] arr = new int[] { 1, 2, 3 };
Console.WriteLine(GetA(arr));
Console.WriteLine(GetB(arr));
Console.WriteLine(GetA(null));
Console.WriteLine(GetB(null));
}
/// <summary>
/// Get the first element, checking for null.
/// </summary>
static int GetA(int[] arr)
{
if (arr != null)
{
return arr[0];
}
else
{
return 0;
}
}
/// <summary>
/// Get the first element, catching exceptions.
/// </summary>
static int GetB(int[] arr)
{
try
{
return arr[0];
}
catch
{
return 0;
}
}
}
Output
1
1
0
0Results. Let's look at the performance results. The error cases never occur in the benchmark: the catch statement is never executed and the parameter is never null. This shows us the cost of null checks versus exceptions that are never thrown.
Data used in benchmark [C#]
int[] arr = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Code tested in tight loops [C#]
int v = GetA(arr);
if (v == 5)
{
i++;
}
int v = GetB(arr);
if (v == 5)
{
i++;
}
Results
Iterations: 100000000
GetA - null checks: 95 ms
GetB - uses try: 607 msAnalysis. We saw that when an exception is not thrown in the C# code, the try/catch block nevertheless has a negative effect on performance. When an exception is actually thrown—which wasn't tested in the benchmark—performance suffers even more.
Because even exception handling constructs that are not executed and have no effect will cause a performance loss, you can change how your code is structured to improve performance. It is best to use try/catch at the outermost block of loops if correctness is preserved.
Exception Optimization
The .NET Framework makes extensive use of a pattern called the Tester-Doer pattern. This refers to functions that do not throw exceptions on errors; instead, these functions return an error code (such as False) and take no action. This pattern improves the performance of certain important functions by avoiding exception handling.
Tester-Doer Pattern
Exposed through an alternative control flow, exception handling facilitates a robust error-handling approach. You can indicate the type of the error by using a derived Exception type. With Exception properties, you can store or read information about errors as they occur. Correct use of exceptions facilitates fast debugging of those errors that always occur in new code.