Использование catch без параметра было полезно в framework 1.x для отлова исключений, генерируемых из неуправляемого кода. Начиная с версии фреймворка 2 (IIRC) все неуправляемые исключения обернуты в управляемый объект Exception, поэтому для перехвата без параметров больше нет необходимости.
Бросок без параметров не является специфическим для улова без параметров, его можно использовать в любом блоке улова. Разница в том, что при повторном отбрасывании исключения с использованием throw;
он не перезаписывает трассировку стека с момента первоначального создания исключения, так что это правильный способ перезапуска исключения.
Вместо использования throw ex;
в блоке перехвата вы должны сгенерировать вновь созданное исключение, содержащее информацию, которую вы хотите добавить, с исходным исключением в качестве внутреннего исключения. Таким образом, вы получаете и исходную точку отказа, и точку, где вы поймали ее и перебросили.
Итак, вы никогда не должны использовать ни одну из комбинаций в примерах в вашем вопросе. Вы всегда указываете тип исключения, и вы либо просто возвращаете исключение:
catch (Exception ex) {
...
throw;
}
или вы выбросили новое исключение с внутренним исключением:
catch (Exception ex) {
...
throw new ApplicationException("Ooops!", ex);
}
Обратите внимание, что вы редко должны ловить базовый класс Exception, но более конкретный класс исключений, который подходит для ожидаемой ошибки. Обычно нет смысла перехватывать исключение, которое вы не знаете, как обработать.