По-видимому, некоторые исключения могут просто потеряться при использовании вложенного оператора using
. Рассмотрим это простое консольное приложение:
using System;
namespace ConsoleApplication
{
public class Throwing: IDisposable
{
int n;
public Throwing(int n)
{
this.n = n;
}
public void Dispose()
{
var e = new ApplicationException(String.Format("Throwing({0})", this.n));
Console.WriteLine("Throw: {0}", e.Message);
throw e;
}
}
class Program
{
static void DoWork()
{
// ...
using (var a = new Throwing(1))
{
// ...
using (var b = new Throwing(2))
{
// ...
using (var c = new Throwing(3))
{
// ...
}
}
}
}
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
// this doesn't get called
Console.WriteLine("UnhandledException:", e.ExceptionObject.ToString());
};
try
{
DoWork();
}
catch (Exception e)
{
// this handles Throwing(1) only
Console.WriteLine("Handle: {0}", e.Message);
}
Console.ReadLine();
}
}
}
Каждый экземпляр Throwing
бросает, когда он удаляется. AppDomain.CurrentDomain.UnhandledException
никогда не вызывается.
Выход:
Throw: Throwing(3) Throw: Throwing(2) Throw: Throwing(1) Handle: Throwing(1)
Я предпочитаю, по крайней мере, иметь возможность регистрировать недостающие Throwing(2)
и Throwing(3)
. Как это сделать, не прибегая к отдельному try/catch
для каждого using
(что бы убить удобство using
)?
В реальной жизни эти объекты часто являются экземплярами классов, над которыми я не контролирую. Они могут или не могут быть брошены, но в случае, если они это сделают, я хотел бы иметь возможность наблюдать за такими исключениями.
Этот вопрос возник, пока я смотрел на уменьшая уровень вложенных using
. Там аккуратный ответ, предлагающий агрегирование исключений. Интересно, как это отличается от стандартного поведения вложенных операторов using
.
[EDITED] Этот вопрос, по-видимому, тесно связан: Следует ли реализовать IDisposable.Dispose(), чтобы он никогда не выбрасывал?