что может привести к тому, что throw сбрасывает стек вызовов (я использую «throw», а не «throw ex»)

AreNotSame действительно ссылается на сравнение, тогда как AreNotEqual делает сравнение равенства.

25
задан Community 23 May 2017 в 12:32
поделиться

3 ответа

Вы должны прочитать эту статью:

Короче говоря, throw обычно сохраняет трассировку стека исходного сгенерированного исключения, но только если исключение не произошло в текущем кадре стека (т.е. метод).

Существует метод PreserveStackTrace (показанный в этой статье блога), который вы используете, который сохраняет исходную трассировку стека следующим образом:

try
{

}
catch (Exception ex)
{
    PreserveStackTrace(ex);
    throw;
}

Но мое обычное решение - либо просто не ловить, но и перебрасывать исключения, как это (если не является абсолютно необходимым), или просто всегда генерировать новые исключения, используя свойство InnerException для распространения исходного исключения:

try
{

}
catch (Exception ex)
{
     throw new Exception("Error doing foo", ex);
}
34
ответ дан 28 November 2019 в 21:03
поделиться

Проблема в том, что Windows сбрасывает начальную точку стека. CLR ведет себя так, как и ожидалось - это всего лишь ограничение поддержки обработки исключений операционной системой хоста. Проблема в том, что на вызов метода может быть только один кадр стека.

Вы можете выделить свои процедуры обработки исключений в отдельный «вспомогательный» метод, который обойдёт ограничения, наложенные Windows SEH, но я не думаю, что это обязательно хорошая идея.

Правильный способ перебрасывать исключение без потери информации стека - это генерировать новое исключение и включать исходное пойманное исключение в качестве внутреннего исключения.

Трудно представить себе очень много случаев, когда вам действительно нужно это сделать. Если вы не обрабатываете исключение и просто перехватываете его, чтобы перебросить, вам, вероятно, не стоит его перехватывать.

9
ответ дан 28 November 2019 в 21:03
поделиться

Обычное повторное преобразование сохраняет все в трассировке стека, за исключением того, что, если существующий метод находится в трассировке стека, номер строки будет перезаписан. Это раздражающее поведение. В C #, если нужно что-то сделать в исключительном случае, но не волнует, что это за исключение, можно использовать шаблон:

  Boolean ok = False;
  try
  {
    do_something();
    ok = True;
  }
  finally
  {
    if (!ok) // An exception occurred!
      handle_exception();
  }

Есть число, где этот шаблон очень полезен; наиболее распространенной будет функция, которая должна возвращать новый IDisposable. Если функция не вернется, одноразовый предмет должен быть очищен. Обратите внимание, что любые операторы «return» в вышеупомянутом блоке «try» должны установить ok в значение true .

В vb.net можно использовать шаблон, который функционально немного лучше, хотя одно место в коде немного странно, с шаблоном:

  Dim PendingException As Exception = Nothing;
  Try
    Do_Something
    PendingException = Nothing ' See note
  Catch Ex As Exception When CopyFirstParameterToSecondAndReturnFalse(Ex, PendingException )
    Throw ' Will never execute, since above will return false
  Finally
    If PendingException IsNot Nothing Then
      .. Handle exception
    EndIf
  End Try

Функция с длинным именем должно быть реализовано очевидным образом. Этот шаблон имеет то преимущество, что делает исключение доступным для кода. Хотя это часто не требуется в ситуациях с обработкой, но не перехвата, есть одна ситуация, когда она может быть неоценимой: если процедура очистки выдает исключение. Обычно, если процедура очистки выдает исключение, любое ожидающее исключение будет потеряно. Однако с помощью приведенного выше шаблона можно заключить ожидающее исключение в исключение очистки.

Одна интересная заметка с приведенным выше кодом: исключение может достигнуть «Catch When», но оператор Try может завершиться нормально. На самом деле не совсем ясно, что должно происходить в таких обстоятельствах, но ясно одно: утверждение «Окончание» не должно действовать так, как если бы исключение находилось на рассмотрении. Очистка PendingException сделает так, что если исключение исчезнет, ​​код будет вести себя так, как будто этого никогда не было. В качестве альтернативы можно заключить в оболочку и выбросить исключение, о котором известно, что оно произошло, поскольку эта ситуация почти наверняка указывает на что-то не так с внутренним кодом обработки исключений.

2
ответ дан 28 November 2019 в 21:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: