C # - Rethrow исключение, не устанавливая его в переменную - PullRequest
6 голосов
/ 02 мая 2011

Как вы все, наверное, знаете, перехват и повторное создание исключения в c # таким образом является злом, поскольку уничтожает трассировку стека:

try
{
    if(dummy)
        throw new DummyException();
}
catch (DummyException ex)
{
    throw ex;
}

Правильный способ перезапустить исключение без потери трассировки стека заключается в следующем:

try
{
    if(dummy)
        throw new DummyException();
}
catch (DummyException ex)
{
    throw;
}

Единственная проблема с этим заключается в том, что я получаю много предупреждений компиляции: «Переменная 'ex' объявлена, но никогда не используется". Если у вас их много, полезное предупреждение может быть скрыто в мусоре. Итак, вот что я сделал:

try
{
    if(dummy)
        throw new DummyException();
}
catch (DummyException)
{
    throw;
}
catch(AnotherException ex)
{
    //handle it
}

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

Заранее спасибо

Edit: Я немного изменил свой код, чтобы прояснить, что я хотел сделать, так как некоторые неправильно поняли

Ответы [ 6 ]

7 голосов
/ 02 мая 2011

Я хотел бы знать, есть ли какие-либо недостатки повторного вызова исключения, для которого не задана переменная.

Нет, недостатков нет вообще.Переменная нужна только в том случае, если вы хотите сослаться на исключение в своем коде, но поскольку вам не нужно делать это с помощью оператора throw, вам вообще не нужна переменная.

Иу вас есть абсолютно правильная идея в попытке устранить «шумные» предупреждения компилятора.Они имеют тенденцию скрывать важные ошибки, которые вы делаете хотите исправить, и всегда важно получить чистую сборку.Лучшее решение - просто переписать код, чтобы использовать безпараметрическое предложение catch.

Однако учтите, что в 82% случаев, которые я вижу *, написать ошибкукод, который использует throw вообще.Как правило, вы не должны ловить исключения, которые вы не знаете, как обрабатывать, и ваша единственная намеченная стратегия «обработки» - это отбрасывать их.В некоторых случаях даже использование throw может сбросить стек вызовов, что приведет к потере важной отладочной информации.Есть также лучшие альтернативы для регистрации исключений для ловли / повторного выброса.Вы можете найти больше информации в ответах на эти вопросы:

Нет ничего плохого в том, чтобы исключения возникали и обрабатывали их все вЦентральное место.Следует помнить, что вы не должны использовать исключения для управления потоком.Но нет ничего плохого в создании исключения в низкоуровневом коде и отображении пользователю сообщения об ошибке выше по стеку в коде пользовательского интерфейса.Прочитайте Microsoft Рекомендации по обработке исключений для получения некоторых общих советов.


* Чуть более процент статистики, которая сделанана месте .

7 голосов
/ 02 мая 2011

Недостатков в этом нет.Вы просто говорите компилятору: «Я планирую перехватить это исключение, но мне не нужна ссылка на фактическое исключение», это не влияет на то, как все выдается или как работают исключения.Ваш последний пример - идеальный способ сделать то, что вы хотите, однако, если вы просто собираетесь сразу throw;, не имея ничего другого в блоке, тогда зачем вообще ловить?

5 голосов
/ 02 мая 2011

Если вы ничего не делаете с DummyException в блоке catch (чего вы не можете, поскольку вы не дали ему идентификатор), почему бы не избавиться от блока try/catch полностью?Например, просто сделайте это:

throw new DummyException();

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

1 голос
/ 14 июля 2011

Зачем ловить и отбрасывать, как это?Почему люди всегда должны предполагать, что они знают каждый случай?Ответ: Операции с базой данных.

Если у вас есть лучший способ сделать это, пожалуйста, поговорите с доктором Протоном, без обид.Имейте в виду, что используется множество различных систем баз данных, но большинство из них поддерживают управление транзакциями (начало / принятие / откат) и имеют интерфейсы C #.

псевдокод (упрощенный случай):

try
{
   db.beginTrans();

   db.doStuff();

   db.doOtherStuff();

   db.commitTrans();
}
catch
{
  db.rollbackTrans();
  throw;
}

Теперь довольно досадно терять детали о том, что doStuff () или doOtherStuff () потерпели неудачу, и я не вижу веской причины, почему C # в этом случае бросил бы информацию о номере строки.Но, похоже,Отсюда поиск в Google и мое последующее прибытие.Если я что-то упустил, пожалуйста, скажите.

1 голос
/ 02 мая 2011

На самом деле генерирование исключения с использованием "throw;" является .Net рекомендацией , поскольку оно сохраняет трассировку стека исключений.

Бросать исключения с использованием "throw ex;" считается худшей практикой , потому что это теряет исходную трассировку стека и его следует избегать.

1 голос
/ 02 мая 2011

Зачем ловить, если вы просто собираетесь повторно бросить?В любом случае, вы можете взглянуть на это предыдущее обсуждение.Хотя не идентично, многое из того, что обсуждается, уместно:

Бросок против повторного броска: тот же результат?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...