Odpowiedz
Tak, blok finally
jest wykonywany, ale przepływ opuszcza blok try
- przez osiągnięcie końca, zwrócenie lub zgłoszenie wyjątku.
Od C# 4 specyfikacji, rozdział 8.10:
Sprawozdania z bloku finally zawsze są wykonywane, gdy kontrola pozostawia spróbować oświadczenie. Jest to prawdą, czy przekazanie sterowania odbywa się w wyniku normalnego wykonania , w wyniku wykonania instrukcji break, continue, goto, return lub jako wynik propagacji wyjątku poza instrukcją try.
(sekcja 8.10 ma dużo więcej szczegółów na ten temat, oczywiście.)
Zauważ, że wartość zwracana jest określana przed finally blok jest wykonywany, więc jeśli to zrobił:
int Test()
{
int result = 4;
try
{
return result;
}
finally
{
// Attempt to subvert the result
result = 1;
}
}
... wartość 4 nadal będzie zwracana, a nie 1 - zadanie w bloku finally
nie będzie miało żadnego efektu.
bloku finally zawsze będą realizowane i nastąpi to przed powrotem z tej metody, dzięki czemu można bezpiecznie pisać kod tak:
try {
return "foo";
} finally {
// This will always be invoked
}
lub jeśli pracujesz z zasobów dyspozycyjnych:
using (var foo = GetFoo())
{
// foo is guaranteed to be disposed even if an exception is thrown
return foo.Bar();
}
Dziękuję za odpowiedź! – Liu
Czy w końcu zostaną wykonane bloki po powrocie z bloków try lub catch w C-Sharp?
TAK
Jeśli tak będzie, przed lub po powrocie?
PRZED
Z obsługi wyjątków dwa-pass, który .NET dziedziczy z okien, nie można dokładnie powiedzieć, że w końcu blok jest wykonywany zanim kontrola przechodzi z powrotem do osoby dzwoniącej.
Ostateczny blok zostanie wykonany po ostatecznie blokach w większej liczbie zagnieżdżonych ramek połączeń, a przed końcowymi blokami i blokiem catch w mniej zagnieżdżonych ramkach wywołania, co jest zgodne z blokiem finally działającym przed powrotem. Ale wszystkie filtry wyjątków między punktem rzutu i punktem catch będą działały przed końcowymi blokami, co oznacza, że w obecności wyjątku niektóre kody wywołujące mogą działać przed blokiem finally.
Gdy formant opuszcza normalnie blok (bez wyjątku odrzuconego), to ostatecznie biegnie zanim kontrola powróci do dzwoniącego.
+1, ponieważ warto tu wspomnieć o wyjątkowych filtrach ... ale nawet przy filtrach wyjątków, z pewnością blok finally jest uruchomiony, zanim sterowanie przejdzie z powrotem do wywołującego. Po prostu filtry wyjątków mogą działać jeszcze wcześniej. –
Cóż, kontrola przechodzi do filtra wyjątków dzwoniącego, następnie do bloku finally, a następnie do obsługi wyjątków dzwoniącego. Tak więc kontrola przechodzi do dzwoniącego zarówno przed, jak i po bloku finally. –
Dzięki za odpowiedź! – Liu
nie ma to większego znaczenia praktycznego, ale blok finally nie jest wykonywany, jeśli wystąpi wyjątek StackOverflowException lub jeśli wywołasz System.Environment.FailFast (...) –
Oczywiście sterowanie nie wraca do wywołującego w ogóle w tych przypadkach. Można powiedzieć, że przepływ * kończy się * zamiast opuszczać blok, tak że oświadczenie Skeeta wciąż trwa. –