логика броска-ловли - PullRequest
       57

логика броска-ловли

4 голосов
/ 30 сентября 2010
try
{
    try
    {
        throw new Exception("From Try");
    }
    catch
    {
        throw new Exception("From Catch");
    }
    finally
    {
        throw new Exception("From Finally");
    }
}
catch (Exception ex)
{
    Console.WriteLine(ex.Message);
}

Вывод кода выше: From Finally.

Почему это не From Catch?

-или-

Как я могу поймать и войтиизвне оба исключения?

Ответы [ 8 ]

6 голосов
/ 30 сентября 2010

Поскольку блок finally выполняется после блока catch, переопределяя исключение.

И когда исключение возникает во время обработки более раннего, первое теряется.

Как я могу поймать и зарегистрировать извне оба исключения?

  1. По не , бросая внутрь блока finally.Это всегда плохая идея.
  2. Если вы хотите войти во внутренний блок catch, используйте throw; или передайте первое исключение как InnerException нового.Вот почему существует InnerException.
3 голосов
/ 30 сентября 2010

Это поведение, как оно определено в спецификации языка C #. Обработка исключения, сгенерированного внутри блока try, прекращается, и вместо этого обрабатывается исключение, сгенерированное в блоке finally.

Соответствующий раздел 8.9.5 Оператор throw объясняет, как распространяются исключения:

  • В текущем члене функции проверяется каждый оператор try, который включает точку выброса. Для каждого оператора S, начиная с самого внутреннего оператора try и заканчивая самым внешним оператором try, оцениваются следующие шаги:

    • Если блок try S содержит точку выброса и если S имеет одно или несколько предложений catch, предложения catch проверяются в порядке появления, чтобы найти подходящий обработчик для исключение. Первое предложение catch, которое указывает тип исключения или базовый тип типа исключения, считается совпадением. Общее предложение catch (§8.10) считается совпадением для любого типа исключения. Если найдено соответствующее предложение catch, распространение исключения завершается передачей управления в блок этого предложения catch.

    • В противном случае, если блок try или блок catch из S охватывают точку выброса, и если S имеет блок finally, управление передается в блок finally. Если блок finally выдает еще одно исключение, обработка текущего исключения прекращается. В противном случае, когда управление достигает конечной точки блока finally, обработка текущего исключения продолжается.

1 голос
/ 30 сентября 2010

Добавьте дополнительный слой блоков try-catch, таких как:

try {
    Exception fromCatch = null;
    try {
        throw new Exception("From Try");
    }
    catch {
        try {
            throw new Exception("From Catch");
        }
        catch (Exception e) {
            // catch failed -> store exception
            fromCatch = e;
        }
    }
    finally {
        try {
            throw new Exception("From Finally");
        }
        catch (Exception e) {
            // i can think of better exception merging... but this shows the idea
            throw new Exception(e.Message, fromCatch);
        }
        // throw fromCatch, in case "From Finally did not happen"
        throw fromCatch;
    }
}
catch (Exception ex) {
    Console.WriteLine(ex.Message);
    if (ex.InnerException != null) {
        Console.WriteLine(ex.InnerException.Message);
    }
}

Отчеты:

From Finally
From Catch

Редактировать: это, очевидно, ответ на второй вопрос, как "почему "ответили достаточно:)

0 голосов
/ 30 сентября 2010

Это очень хороший вопрос, и он довольно сложный.Давайте пройдем этот шаг за шагом:

try
{
    throw new Exception("From Try");
}
catch
{
    throw new Exception("From Catch");
}

В приведенном выше коде Exception («From Try») выбрасывается и перехватывается предложением catch (пока довольно просто).Предложение catch выдает свое собственное исключение, которое мы обычно ожидаем (потому что catch вложен в больший блок try-catch), чтобы быть пойманным немедленно, но ...

finally
{
   throw new Exception("From Finally");
}

Предложение finally, который гарантированно (попытается) выполнить, приходит первым и выдает свое собственное исключение, перезаписывая исключение ("From Catch") , которое было выдано ранее.

«Обычное использование catch и finally вместе - получение и использование ресурсов в блоке try, обработка исключительных обстоятельств в блоке catch и освобождение ресурсов в блоке finally» - Статья MSDN

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

0 голосов
/ 30 сентября 2010

Поскольку блок finally всегда выполняется.

try 
{ 
    try 
    { 
        throw new Exception("From Try"); 
        // (1) A new exception object A is created here and thrown.
    } 
    catch // (2) Exception object A is catched.
    { 
        throw new Exception("From Catch"); 
        // (3) A new exception object B is created here and thrown.
    } 
    finally // (4) Execution is forced to continue here!
    { 
        throw new Exception("From Finally"); 
        // (5) A new exception object C is created here and thrown.
    } 
} 
catch (Exception ex) // (6) Exception object C is catched.
{ 
    Console.WriteLine(ex.Message); 
} 

Каждый новый исключительный объект в шагах (3) и (5) отбрасывает предыдущий.Поскольку блок finally всегда выполняется, остается только объект исключения C из шага (5).

0 голосов
/ 30 сентября 2010

Ваш код вызывает исключение new из каждой части оператора try / catch / finally.По сути, вы глотаете предыдущее исключение при создании новой ошибки.Вы можете добавить свое сообщение «Из попытки» в свое сообщение «Из улова», например,

catch(Exception ex)
{
    throw new Exception(ex.Message + ":" + "From Catch");
}

Я не знаю, как вы могли бы связать это в конечном итоге.

0 голосов
/ 30 сентября 2010

finally происходит несмотря ни на что.Независимо от того, было ли исключение в попытке или улове.Таким образом, вы видите «From Наконец».(На самом деле это целое предназначение предложения finally. Таким образом, вы можете поместить туда код, который очистит ресурсы и тому подобное, несмотря ни на что - даже если есть исключение.)

0 голосов
/ 30 сентября 2010

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

не уверен, понимаю ли я часть2 вопроса

...