try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
У наведеному вище блоці, коли називається остаточний блок? Перед викиданням е або нарешті дзвонить і потім ловити?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
У наведеному вище блоці, коли називається остаточний блок? Перед викиданням е або нарешті дзвонить і потім ловити?
Відповіді:
Це буде викликано після повторного відкидання e (тобто після виконання блоку catch)
редагування цього 7 років пізніше - одна важлива примітка полягає в тому, що якщо eблок "try / catch" не потрапляє далі на стек виклику або обробляється глобальним обробником винятків, finallyблок може взагалі не виконуватись.
finallyне виконується , якщо виключення кинуто в попередньому catchніколи не спіймані в зовнішньому try- catchблок!
Чому б не спробувати:
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");
}
}
outer try inner try inner catch Unhandled Exception: System.DivideByZeroException...
Прочитавши всі відповіді тут, схоже, що остаточна відповідь залежить :
Якщо ви повторно кидаєте виняток у блок лову, і цей виняток потрапляє всередину іншого блоку лову, все виконується відповідно до документації.
Однак, якщо повторне вилучення вилучення є без обробки, остаточно ніколи не виконується.
Я перевірив цей зразок коду в VS2010 w / C # 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: повторно киньте всередину іншого блоку спробу:
--повторіть спробу
---- внутрішній спробу
---- внутрішній ловить
---- внутрішній нарешті - нарешті
лову
--укінець нарешті
Huzzah!Приклад 2: повторний кидок за межі інший Ьгі блоку:
--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;, оскільки це збереже початковий слід стека замість створення нового.
finallyблок буде запущений після catchблоку (навіть якщо блок лову повторно виключає виняток), що і намагається проілюструвати мій фрагмент.
tryблоку моєї відповіді є "спробувати-улов". Я намагаюся пояснити поведінку 3-х частинної конструкції за допомогою двох 2-х частинних конструкцій. Я не бачу жодних ознак другого tryблоку в оригінальному запитанні, тому я не розумію, звідки ви це дістаєте.
Якщо всередині блоку обробника лову є необроблений виняток, нарешті блок називається рівно нульовим разів
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: \ користувачів \ адміністратор \ документи \ TestExceptionNesting \ bin \ Release> TestExceptionNesting.exe
у спробі
в улові
Неопрацьоване виняток: System.DivideByZeroException: Спроба розділити на нуль. у TestExceptionNesting.Program.Main (String [] аргументи) в C: \ users \ administrator \ документи \ TestExceptionNesting \ TestExceptionNesting.cs: рядок 22
C: \ користувачів \ адміністратор \ документи \ TestExceptionNesting \ bin \ release>
Мені сьогодні було задано це питання під час інтерв'ю, і інтерв'юер продовжував повертатися назад "ти впевнений, що нарешті не телефонуєш?" Я був невпевнений, чи малося на увазі підступне запитання чи інтерв'юер мав на увазі щось інше і написав неправильний код для налагодження, тому я прийшов додому і спробував це (побудувати та запустити, ніякої взаємодії з налагодженням), просто щоб подумати про це відпочинок.
Тестуючи програму консолі C #, остаточний код був виконаний після того, як викинутий виняток: "Діалог помилок програми" існував і після того, як ви вибрали опцію "Закрити програму", нарешті блок був виконаний у цьому вікні консолі. Але встановивши точку злому всередині остаточно кодового блоку, я ніколи не можу його вдарити. Відладчик постійно зупиняється на заяві про кидок. Ось мій тестовий код:
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