.NET 4.0 introduced a new type of exception, the AggregateException which as the name implies allows to aggregate several exceptions inside a single throw-able exception instance.
It is extensively used in the Task Parallel Library (TPL) and besides representing a simple collection of exceptions can also be used to represent a set of exceptions in a tree-like structure.
Besides its InnerExceptions property which is a read-only collection of exceptions, the most relevant members of this new type are the methods Flatten and Handle. The former allows to flatten a tree hierarchy removing the need to recur while working with an aggregate exception. For example, if we would flatten the exception tree illustrated in the previous figure the result would be:
The other method, Handle, accepts a predicate that is invoked for each aggregated exception and returns a boolean indicating if each exception is handled or not. If at least one exception goes unhandled then Handle throws a new AggregateException containing only the unhandled exceptions. The following code snippet illustrates this behavior and also another scenario where an aggregate exception proves useful – single threaded batch processing.
static void Main()
{
try
{
ConvertAllToInt32("10", "x1x", "0", "II");
}
catch (AggregateException errors)
{
// Contained exceptions are all FormatException
// so Handle does not thrown any exception
errors.Handle(e => e is FormatException);
}
try
{
ConvertAllToInt32("1", "1x", null, "-2", "#4");
}
catch (AggregateException errors)
{
// Handle throws a new AggregateException containing
// the exceptions for which the predicate failed.
// In this case it will contain a single ArgumentNullException
errors.Handle(e => e is FormatException);
}
}
private static int[] ConvertAllToInt32(params string[] values)
{
var errors = new List<Exception>();
var integers = new List<int>();
foreach (var item in values)
{
try
{
integers.Add(Int32.Parse(item));
}
catch (Exception e) { errors.Add(e); }
}
if (errors.Count > 0)
throw new AggregateException(errors);
return integers.ToArray();
}