try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
В вышеприведенном блоке, когда называется блок finally? Перед выбросом e или, наконец, вызывается, а затем ломается?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
В вышеприведенном блоке, когда называется блок finally? Перед выбросом e или, наконец, вызывается, а затем ломается?
Он будет вызываться после повторного выброса e (т.е. после выполнения блока catch)
редактирование этого 7 лет спустя - важно отметить, что если e
не попадает в блок try/catch дальше в стек вызовов или обрабатывается глобальным обработчиком исключений, тогда блок finally
никогда не может выполняться в все.
Почему бы не попробовать:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
с кодом (отформатированным для вертикального пространства):
static void Main() {
try {
Console.WriteLine("outer try");
DoIt();
} catch {
Console.WriteLine("outer catch");
// swallow
} finally {
Console.WriteLine("outer finally");
}
}
static void DoIt() {
try {
Console.WriteLine("inner try");
int i = 0;
Console.WriteLine(12 / i); // oops
} catch (Exception e) {
Console.WriteLine("inner catch");
throw e; // or "throw", or "throw anything"
} finally {
Console.WriteLine("inner finally");
}
}
После прочтения всех ответов здесь выглядит, как окончательный ответ зависит от:
Если вы повторно выбрали исключение в блоке catch и это исключение попало в другой блок catch, все будет выполняться в соответствии с документацией.
Однако, если исключение re-trown не обрабатывается, то, наконец, никогда не выполняется.
Я тестировал этот пример кода в VS2010 w/С# 4.0
static void Main()
{
Console.WriteLine("Example 1: re-throw inside of another try block:");
try
{
Console.WriteLine("--outer try");
try
{
Console.WriteLine("----inner try");
throw new Exception();
}
catch
{
Console.WriteLine("----inner catch");
throw;
}
finally
{
Console.WriteLine("----inner finally");
}
}
catch
{
Console.WriteLine("--outer catch");
// swallow
}
finally
{
Console.WriteLine("--outer finally");
}
Console.WriteLine("Huzzah!");
Console.WriteLine();
Console.WriteLine("Example 2: re-throw outside of another try block:");
try
{
Console.WriteLine("--try");
throw new Exception();
}
catch
{
Console.WriteLine("--catch");
throw;
}
finally
{
Console.WriteLine("--finally");
}
Console.ReadLine();
}
Вот результат:
Пример 1: повторите бросок внутри другого блока try:
--outer try
---- внутренняя попытка
---- внутренний улов
---- внутреннее окончательное
- уловный лоток
- окончательно Ура!Пример 2: повторный выброс за пределы другого блока try:
--try
--catchНеобработанное исключение: System.Exception: выбрано исключение типа "System.Exception".
в ConsoleApplication1.Program.Main() в C:\local source\ConsoleApplication1\Program.cs: строка 53
Ваш пример будет вести себя одинаково с этим кодом:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
В качестве побочного примечания, если вы действительно имеете в виду throw e;
(т.е. бросаете то же самое исключение, которое вы только что поймали), гораздо лучше просто сделать throw;
, так как это сохранит исходную трассировку стека вместо создания новый.
Если в блоке обработчика catch есть необработанное исключение, блок finally вызывается точно ноль раз
static void Main(string[] args)
{
try
{
Console.WriteLine("in the try");
int d = 0;
int k = 0 / d;
}
catch (Exception e)
{
Console.WriteLine("in the catch");
throw;
}
finally
{
Console.WriteLine("In the finally");
}
}
Вывод:
C:\Users\Администратор\документы\TestExceptionNesting\Bin\Release > TestExceptionNesting.exe
в try
в catch
Необработанное исключение: System.DivideByZeroException: Попытка разделить на ноль. в TestExceptionNesting.Program.Main(String [] args) в C:\users\administrator\documents\TestExceptionNesting\TestExceptionNesting.cs: строка 22
C:\Users\Администратор\документы\TestExceptionNesting\Bin\выпуск >
Мне задали этот вопрос сегодня на собеседовании, и интервьюер продолжал возвращаться. "Вы уверены, что наконец-то не вызвали?" Я был не уверен, что это был спорный вопрос, или у интервьюера было что-то другое, и он написал неправильный код для отладки, поэтому я пришел домой и попробовал (построил и запустил, никакого взаимодействия с отладчиком), просто чтобы понять остальное.
Простым способом сказать также является отладка вашего кода и уведомление при его окончательном вызове.
Тестирование с помощью приложения С# Console, код finally был выполнен после того, как выбрано исключение: "Диалог ошибок приложения" существует, и после того, как вы выбрали опцию "Закрыть программу", блок finally был выполнен в этом окне консоли. Но установив точку прерывания внутри кода кода finally, я никогда не смогу его ударить. Отладчик продолжает останавливаться в инструкции throw. Вот мой тестовый код:
class Program
{
static void Main(string[] args)
{
string msg;
Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
}
static int GetRandomNumber(out string errorMessage)
{
int result = 0;
try
{
errorMessage = "";
int test = 0;
result = 3/test;
return result;
}
catch (Exception ex)
{
errorMessage = ex.Message;
throw ex;
}
finally
{
Console.WriteLine("finally block!");
}
}
}
Отладка в VS2010 -.NET Framework 4.0