.net Блок блокировки исключений

Какая разница между следующими блоками catch?

try
{
    ...
}
catch
{
    ...
}

и

try
{
    ...
}
catch(Exception)
{
    ...
}

Я понимаю, что в любом случае экземпляр исключения недоступен, но есть ли что-нибудь, что я могу сделать с тем, что невозможно с другим?

Ответ 1

Они почти одинаковы.

Из спецификации языка С#, раздел 8.10:

Некоторые языки программирования могут поддерживать исключения, которые не могут быть представлены как объекты, происходящие из System.Exception, хотя такие исключения никогда не могут быть сгенерированы кодом С#. Для исключения таких исключений может быть использовано общее правило catch. Таким образом, общее предложение catch является семантически отличным от того, которое указывает тип System.Exception, поскольку первое может также перехватывать исключения из других языков.

Обратите внимание, что в то время как С# отличается между двумя, они фактически те же, что и для .NET 2.0, как отмечено этот блог:

Благодаря недавнему изменению в версии 2.0 CLR, если у вас был код, который решил бросить, скажем, int (System.Int32) где-то, CLR теперь обернет его с помощью RuntimeWrappedException, а компилятор будет обновлен до дайте вам предупреждение, что второе выше предложение теперь является мертвым кодом

warning CS1058: A previous catch clause already catches all exceptions. All non-exceptions thrown will be wrapped in a System.Runtime.CompilerServices.RuntimeWrappedException

Для того, как CLR знает, как это сделать для вашей сборки, вы заметите, что компилятор теперь добавляет RuntimeCompatibilityAttribute к вашим сборкам, которые сообщают ему:
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = {property bool 'WrapNonExceptionThrows' = bool(true)}

Ответ 2

catch без аргументов будут улавливать исключения, не совместимые с CLS, в отличие от catch (Exception).

Ответ 3

Из Почему catch (исключение)/пустой улов плохой

Ошибки выписки могут быть столь же плохими, в зависимости от кода MSIL, который генерирует ваш язык. С# превращает пустой оператор catch в catch (System.Object), что означает, что вы завершаете все исключения - даже исключения, отличные от CLS. VB лучше себя ведет, превращая пустую инструкцию catch в catch e как System.Exception, которая ограничивает вас перехватом CLS-совместимых исключений.

Ответ 4

Если вы посмотрите на сгенерированный ИЛ здесь разницу:

catch(Exception){}:

catch [mscorlib]System.Exception
{}

и просто поймать:

catch{}:

catch [mscorlib]System.Object
{}

Итак, теоретически, если вы создаете язык, который может иметь исключения, не наследуемые от System.Exception, будет разница...

Ответ 5

Не придерживающиеся CLS языки (например, С++/CLI) могут вызывать объекты, не полученные из класса System.Exception. Первый пример кода позволит вам выполнить код в блоке catch, хотя вы не можете исследовать сам брошенный объект. Это почти никогда не проблема, но это может быть.

Ответ 6

Я не верю, что есть разница, и такой инструмент, как Resharper, скажет вам, что catch(Exception) избыточен во втором экземпляре, ЕСЛИ вы также не добавили другие блоки обработки исключений catch(SomeSubclassException) до Exception для применения другая логика обработки исключений для других условий исключения.