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

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

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

Например:

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

8 ответов

Решение

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

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

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

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

Я бы добавил эти комментарии:

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

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

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

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

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

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

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

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

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

Разве это не хорошо?

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

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
}

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

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

catch(Exception e)
{
}

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

Другие вопросы по тегам