В чем разница между throw и throw ex в C#?

«В чем разница между throw и throw ex в C#?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевое отличие — в сохранении оригинальной трассировки стека (stack trace), что критично для отладки.

  • throw; — повторно выбрасывает перехваченное исключение, сохраняя полный стек вызовов.
  • throw ex; — выбрасывает то же исключение заново, но сбрасывает точку возникновения на текущую строку, обрезая стек вызовов.

Пример, демонстрирующий проблему:

void InnerMethod() {
    throw new InvalidOperationException("Ошибка на низком уровне");
}

void OuterMethod() {
    try {
        InnerMethod();
    }
    catch (Exception ex) {
        // ПЛОХО: стек будет указывать на эту строку, а не на InnerMethod
        // throw ex;

        // ХОРОШО: стек сохранит путь: OuterMethod -> InnerMethod
        throw;
    }
}

Когда что использовать:

  1. Всегда используйте throw; при повторной генерации того же исключения в блоке catch. Это стандартная практика.
  2. throw ex; практически никогда не нужен. Его единственное гипотетическое применение — намеренное сокрытие внутренней структуры кода (security through obscurity), что является антипаттерном.
  3. Если нужно создать новое исключение с дополнительным контекстом, оберните оригинальное:
    catch (Exception ex) {
    throw new ApplicationException("Не удалось обработать запрос", ex); // ex становится InnerException
    }