Ответ 1
Я не уверен, что это ограничение относится к языку С#, CLI или реализации Microsoft, но ваш второй пример - это случай, когда требуется явный вызов Exception.InternalPreserveStackTrace
, как описано в следующем сообщении, Поскольку этот метод internal
, его обычно нужно вызывать через отражение. Проблемы с производительностью, связанные с этим, могут быть почти полностью устранены путем создания Action<Exception>
для вызова, как показано в конце этого ответа.
Ссылка: Повторное удаление исключений и сохранение полной трассировки стека вызовов
Изменить: После пересмотра ECMA-335 Partition я §12.4.2 (Обработка исключений) и раздела III §4.24 (rethrow) теперь я считаю, что поведение, которое вы видите, является семантической ошибкой в CLR (реализация Microsoft CLI). Единственная конкретная ссылка на поведение: "A rethrow
не меняет трассировку стека в объекте". В случае, описанном здесь, ретролл фактически изменяет трассировку стека, заставляя PreserveStackTrace
взломать обходной путь для известного недостатка CLR.
static void LongFaultyMethod()
{
try
{
int x = 20;
int y = x / (x - 20);
}
catch (Exception ex)
{
PreserveStackTrace(ex); // <-- add this line
throw;
}
}
PreserveStackTrace
Вот оптимизация одной из этой записи в блоге:
private static readonly Action<Exception> _internalPreserveStackTrace =
(Action<Exception>)Delegate.CreateDelegate(
typeof(Action<Exception>),
typeof(Exception).GetMethod(
"InternalPreserveStackTrace",
BindingFlags.Instance | BindingFlags.NonPublic));
public static void PreserveStackTrace(Exception e)
{
_internalPreserveStackTrace(e);
}