AggregateExceptionで集約された例外に対する処理いろいろ


## AggregateException.InnerExceptions

InnerExceptionsプロパティに集約された例外がセットされている。

今回は複数のタスクをWait()しているが、タスクが、アタッチされた子タスクの親である場合にも例外が集約される。

```csharp
public class AggregateExceptionExample
{
    public static void Run() 
    {
        var tasks = new List<Task>();

        tasks.Add(Task.Factory.StartNew(() => { throw new Exception("Error1"); }));
        tasks.Add(Task.Factory.StartNew(() => { throw new Exception("Error2"); }));
        tasks.Add(Task.Factory.StartNew(() => { throw new Exception("Error3"); }));

        try
        {
            Task.WaitAll(tasks.ToArray());
        }
        catch (AggregateException exc)
        {
            //Error1 ～ Error3 が出力される
            foreach (var e in exc.InnerExceptions)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}
```


## AggregateException.Handle()

Handleに例外に対する対応実施の有無を返すラムダ式を指定することで、フィルタリング的な挙動を行うことができる。

```csharp
public class AggregateExceptionExample2Runnter
{
    public static void Run()
    {
        try
        {
            AggregateExceptionExample2.Run();
        }
        catch (AggregateException exc)
        {
            //Error1 と Error2 が出力される
            foreach (var e in exc.InnerExceptions)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}

public class MyException : Exception
{
    public MyException(string msg) : base(msg) { }
}

public class AggregateExceptionExample2
{
    public static void Run()
    {
        var tasks = new List<Task>();

        tasks.Add(Task.Factory.StartNew(() => { throw new Exception("Error1"); }));
        tasks.Add(Task.Factory.StartNew(() => { throw new MyException("MyError"); }));
        tasks.Add(Task.Factory.StartNew(() => { throw new Exception("Error2"); }));

        try
        {
            Task.WaitAll(tasks.ToArray());
        }
        catch (AggregateException exc)
        {
            exc.Handle((e) =>
            {
                //true：例外処理した、false：例外処理していない
                return e.GetType() == typeof(MyException);
            });
        }
    }
}
```

## AggregateException.Flatten()

Flatten()でAggregateExceptionのネストを平坦化することができる。

```csharp
public class AggregateExceptionExample3
{
    public static void Run()
    {
        var tasks = new List<Task>();

        tasks.Add(Task.Factory.StartNew(() => { throw new Exception("Error1"); }));
        tasks.Add(Task.Factory.StartNew(() => { throw new Exception("Error2"); }));
        tasks.Add(Task.Factory.StartNew(() => {
            var tasks2 = new List<Task>();
            tasks2.Add(Task.Factory.StartNew(() => { throw new Exception("Error3-1"); }));
            tasks2.Add(Task.Factory.StartNew(() => { throw new Exception("Error3-2"); }));
            tasks2.Add(Task.Factory.StartNew(() => { throw new Exception("Error3-3"); }));
            Task.WaitAll(tasks2.ToArray());
        }));

        try
        {
            Task.WaitAll(tasks.ToArray());
        }
        catch (AggregateException exc)
        {
            foreach (var e in exc.Flatten().InnerExceptions)
            {
                Console.WriteLine(e.Message);
            }
        }
    }
}
```