try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
Когда в приведенном выше блоке вызывается блок finally? До того как бросить е или это окончательно называется, а потом ловить?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
Когда в приведенном выше блоке вызывается блок finally? До того как бросить е или это окончательно называется, а потом ловить?
Ответы:
Он будет вызываться после повторного вызова 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...
После прочтения всех ответов здесь, похоже , окончательный ответ зависит :
Если вы повторно генерируете исключение в блоке catch, и это исключение перехватывается внутри другого блока catch, все выполняется в соответствии с документацией.
Однако, если повторное исключение не обработано, finally никогда не выполняется.
Я тестировал этот образец кода в VS2010 с 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: повторный бросок внутрь другого блока try:
--outer try
---- внутренняя попытка
---- внутренняя ловушка
---- внутренняя, наконец -
внешняя
ловушка --outer finally Huzzah
!Пример 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;, так как это сохранит исходную трассировку стека, а не создает новую.
finallyБлок фактически будет работать после catchблока (даже если блок поймать rethrows исключения), что и мой фрагмент кода пытается проиллюстрировать.
tryблока в моем ответе есть «попробуй-поймай». Я пытаюсь объяснить поведение конструкции из трех частей, используя две конструкции из двух частей. Я не вижу никаких признаков второго tryблока в исходном вопросе, поэтому я не понимаю, откуда вы это взяли.
Если внутри блока обработчика 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 \ Администратор \ Documents \ TestExceptionNesting \ Bin \ Release> TestExceptionNesting.exe
в попытке
в улове
Необработанное исключение: System.DivideByZeroException: попытка разделить на ноль. в TestExceptionNesting.Program.Main (String [] args) в C: \ users \ administrator \ documents \ TestExceptionNesting \ TestExceptionNesting.cs: строка 22
C: \ Users \ Администратор \ Documents \ TestExceptionNesting \ Bin \ выпуск>
Мне задали этот вопрос сегодня на интервью, и интервьюер все время повторял: «Вы уверены, что наконец-то не позвонили?» Я не был уверен, имел ли это в виду вопрос с подвохом, или интервьюер имел в виду что-то еще и написал мне неправильный код для отладки, поэтому я пришел домой и попробовал его (сборка и запуск, без взаимодействия с отладчиком), просто чтобы сосредоточиться на остальное.
При тестировании с консольным приложением C # код 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