Более элегантная обработка исключений, чем несколько ловушек?

Используя С#, есть ли лучший способ обрабатывать несколько типов исключений, а не пучок уродливых блоков catch?

Что считается лучшей практикой для такого типа ситуаций?

Например:

try
{
    // Many types of exceptions can be thrown
}
catch (CustomException ce)
{
    ...
}
catch (AnotherCustomException ace)
{
    ...
}
catch (Exception ex)
{
    ...
}

Ответ 1

На мой взгляд, куча "уродливых" блоков catch - лучший способ справиться с этой ситуацией.

Я предпочитаю, чтобы это было очень явным. Вы явно указываете, какие исключения вы хотите обрабатывать, и как их следует обрабатывать. Другие формы попыток объединить обработку в более сжатые формы теряют читаемость в большинстве случаев.

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

Ответ 2

Я согласен с Ридом: это лучший подход.

Я бы добавил следующие комментарии:

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

Не переусердствуйте от использования блоков catch. Во многих случаях, когда вы не можете разрешить исключение, лучше всего просто дать исключению пузырь до центральной точки (например, Page_Error) и поймать ее там. Затем вы регистрируете исключение и выводите сообщение пользователю.

Ответ 3

О том, что вы можете сделать, это только эмуляция фильтров исключений VB.NET:

try {
    DoSomething();
} catch (Exception e) {
    if (!ex is CustomException && !ex is AnotherCustomException) {
       throw;
    }
    // handle
}

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

Ответ 4

К сожалению, С# не имеет фильтров пользовательских исключений, таких как VB.NET, поэтому вы ограничены:

  • Ловля общего предка ко всем исключениям. Это может быть или не быть тем, что вы хотите, потому что могут быть другие типы исключений потомков, которые вы не хотите улавливать.
  • Перемещение логики обработки исключений в другой метод и вызов этого из каждого обработчика.
  • Повторение логики исключений для каждого обработчика.
  • Перемещение логики обработки исключений на язык, который поддерживает фильтры, такие как VB.NET.

Ответ 5

Если вам нужно написать действительно большое количество кода, как это, я бы предложил проверить AOP. Я лично использую PostSharp. Затем вы можете скрыть весь код обработки исключений в аспектах.

Ответ 6

Вы должны проверить блок управления Блок обработки исключений. Это позволяет гораздо более мелкозернистое управление исключениями посредством политик (политики упаковки, политики распространения, политики замещения, политики ведения журналов и т.д.). Вы можете использовать его для стандартизации способа кодирования блока исключений и использования конфигурации для обработки точно, что происходит с конкретный тип исключения.

Ответ 7

Неужели это плохо?

Если вы хотите обработать только одно исключение:

try
{
    // Many types of exceptions can be thrown
}
catch (TheExceptionIWantToHandle ex)
{
    // handle it
}
catch (Exception ex)
{
    // suppress all other exceptions
}

Если вы хотите обрабатывать все исключения, кроме одного:

try
{
    // Many types of exceptions can be thrown
}
catch (TheExceptionIDoNotWantToHandle ex)
{
    // suppress all other exceptions
}
catch (Exception ex)
{
    // handle it
}

хорошо, не хорошо?

Ответ 8

Поймайте только то, что вам нужно для конкретного решения, и оставьте

catch(Exception e)
{
}

для всего остального (или пропустить его и передать исключения в стек)