Если наконец блок выдает исключение, что точно происходит?
А именно, что происходит, если исключение выдается на полпути через наконец блок. Остальная часть операторов (после) в этом блоке вызывается?
Я знаю, что исключения распространят вверх.
Если блок finally вызывает исключение, что именно происходит?
Это исключение распространяется все выше и выше и будет (может) обрабатываться на более высоком уровне.
Ваш блок finally не будет завершен после того, как возникнет исключение.
Если блок finally выполнялся во время обработки более раннего исключения, то первое исключение теряется.
Спецификация языка C # 4 § 8.9.5: Если блок finally вызывает другое исключение, обработка текущего исключения прекращается.
Для подобных вопросов я обычно открываю пустой проект консольного приложения в Visual Studio и пишу небольшой пример программы:
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
catch (Exception ex)
{
Console.WriteLine("Inner catch block handling {0}.", ex.Message);
throw;
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
Когда вы запустите программу, вы увидите точный порядок выполнения блоков catch
и finally
. Обратите внимание, что код в блоке finally после выброса исключения не будет выполнен (на самом деле, в этом примере программы Visual Studio даже предупредит вас, что обнаружила недоступный код):
Inner catch block handling exception thrown from try block. Inner finally block Outer catch block handling exception thrown from finally block. Outer finally block
Additional Remark
Как отметил Михаил Даматов, исключение из блока try
будет "съедено", если вы не обработаете его во внутреннем блоке catch
. На самом деле, в приведенном выше примере повторно отброшенное исключение не появляется во внешнем блоке catch. Чтобы сделать это еще более понятным, посмотрите на следующий слегка измененный пример:
using System;
class Program
{
static void Main(string[] args)
{
try
{
try
{
throw new Exception("exception thrown from try block");
}
finally
{
Console.WriteLine("Inner finally block");
throw new Exception("exception thrown from finally block");
Console.WriteLine("This line is never reached");
}
}
catch (Exception ex)
{
Console.WriteLine("Outer catch block handling {0}.", ex.Message);
}
finally
{
Console.WriteLine("Outer finally block");
}
}
}
Как видно из вывода, внутреннее исключение "потеряно" (т.е. проигнорировано):
Inner finally block Outer catch block handling exception thrown from finally block. Outer finally block
public void MyMethod()
{
try
{
}
catch{}
finally
{
CodeA
}
CodeB
}
Способ обработки исключений, выброшенных кодомА и кодомВ, одинаков.
Исключение, выброшенное в блоке finally
, не имеет ничего особенного, рассматривайте его как исключение, выброшенное кодом B.
Если есть ожидающее исключение (когда блок try
имеет finally
, но не catch
]), новое исключение заменяет тот.
Если нет ожидающих исключения, это работает так же, как выброс исключения за пределами блока finally
.
Выдает исключение;) Вы можете перехватить это исключение в другом предложении catch.