Cokolwiek jest w środku, bloki są zawsze wykonywane (prawie) zawsze, więc jaka jest różnica między umieszczeniem w nim kodu a pozostawieniem go niezamkniętego?
Cokolwiek jest w środku, bloki są zawsze wykonywane (prawie) zawsze, więc jaka jest różnica między umieszczeniem w nim kodu a pozostawieniem go niezamkniętego?
Odpowiedzi:
Kod w bloku wreszcie zostanie wykonany niezależnie od tego, czy istnieje wyjątek. Jest to bardzo przydatne, jeśli chodzi o niektóre funkcje porządkowe, które musisz zawsze działać jak zamykanie połączeń.
Zgaduję, że twoje pytanie brzmi: dlaczego powinieneś to zrobić:
try
{
doSomething();
}
catch
{
catchSomething();
}
finally
{
alwaysDoThis();
}
Kiedy możesz to zrobić:
try
{
doSomething();
}
catch
{
catchSomething();
}
alwaysDoThis();
Odpowiedź jest taka, że wiele razy kod w instrukcji catch zwróci wyjątek lub wyłączy się z bieżącej funkcji. W tym ostatnim kodzie „alwaysDoThis ();” Wywołanie nie zostanie wykonane, jeśli kod w instrukcji catch wyświetli zwrot lub zgłosi nowy wyjątek.
Wskazano już na większość zalet używania try-wreszcie, ale pomyślałem, że dodam ten:
try
{
// Code here that might throw an exception...
if (arbitraryCondition)
{
return true;
}
// Code here that might throw an exception...
}
finally
{
// Code here gets executed regardless of whether "return true;" was called within the try block (i.e. regardless of the value of arbitraryCondition).
}
Takie zachowanie sprawia, że bardzo przydatne w różnych sytuacjach, szczególnie gdy trzeba wykonać czyszczenia (zasoby wrzucać), choć przy użyciu bloku jest często lepiej w tym przypadku.
za każdym razem, gdy korzystasz z niezarządzanych żądań kodu, takich jak czytniki strumieniowe, żądania db itp. i chcesz złapać wyjątek, a następnie użyj try catch w końcu i zamknij strumień, czytnik danych itp. w końcu, jeśli nie zrobisz tego, gdy wystąpi błąd, połączenie nie zostanie zamknięte, to naprawdę źle z żądaniami db
SqlConnection myConn = new SqlConnection("Connectionstring");
try
{
myConn.Open();
//make na DB Request
}
catch (Exception DBException)
{
//do somehting with exception
}
finally
{
myConn.Close();
myConn.Dispose();
}
jeśli nie chcesz złapać błędu, użyj
using (SqlConnection myConn = new SqlConnection("Connectionstring"))
{
myConn.Open();
//make na DB Request
myConn.Close();
}
a obiekt połączenia zostanie usunięty automatycznie, jeśli wystąpi błąd, ale błąd nie zostanie przechwycony
Ponieważ w końcu zostanie wykonany, nawet jeśli nie obsłużysz wyjątku w bloku catch.
Wreszcie instrukcje mogą być wykonywane nawet po powrocie.
private int myfun()
{
int a = 100; //any number
int b = 0;
try
{
a = (5 / b);
return a;
}
catch (Exception ex)
{
Response.Write(ex.Message);
return a;
}
// Response.Write("Statement after return before finally"); -->this will give error "Syntax error, 'try' expected"
finally
{
Response.Write("Statement after return in finally"); // --> This will execute , even after having return code above
}
Response.Write("Statement after return after finally"); // -->Unreachable code
}
finally
, jak w:
try {
// do something risky
} catch (Exception ex) {
// handle an exception
} finally {
// do any required cleanup
}
to gwarantowana możliwość wykonania kodu po twoim try..catch
bloku, bez względu na to, czy blok try rzucił wyjątek.
To sprawia, że jest idealny do takich rzeczy, jak uwalnianie zasobów, połączenia db, uchwyty plików itp.
wyjaśnię użycie w końcu z wyjątkiem czytnika plików Przykład
try{ StreamReader strReader = new StreamReader(@"C:\Ariven\Project\Data.txt"); Console.WriteLine(strReader.ReadeToEnd()); StreamReader.Close(); } catch (Exception ex) { Console.WriteLine(ex.Message); }
w powyższym przykładzie, jeśli plik o nazwie dane.txt brakuje wyjątek zostanie wyrzucony i będą obsługiwane, ale oświadczenie o nazwie StreamReader.Close();
nigdy nie zostanie wykonana.
Z tego powodu zasoby związane z czytnikiem nigdy nie zostały wydane.
StreamReader strReader = null; try{ strReader = new StreamReader(@"C:\Ariven\Project\Data.txt"); Console.WriteLine(strReader.ReadeToEnd()); } catch (Exception ex){ Console.WriteLine(ex.Message); } finally{ if (strReader != null){ StreamReader.Close(); } }
Happy Coding :)
Uwaga: „@” służy do tworzenia ciągów ciągłych , aby uniknąć błędu „Nierozpoznana sekwencja ucieczki”. Symbol @ oznacza dosłowne odczytanie tego ciągu i w przeciwnym razie nie należy interpretować znaków kontrolnych.
Załóżmy, że musisz ustawić kursor z powrotem na domyślny wskaźnik zamiast kursora oczekującego (klepsydra). Jeśli wyjątek zostanie zgłoszony przed ustawieniem kursora i nie spowoduje całkowitego zawieszenia aplikacji, możesz pozostać z mylącym kursorem.
Czasami nie chcesz obsłużyć wyjątku (brak bloku catch), ale chcesz wykonać kod czyszczenia.
Na przykład:
try
{
// exception (or not)
}
finally
{
// clean up always
}
Wreszcie blok jest cenny do czyszczenia wszelkich zasobów przydzielonych w bloku try, a także do uruchamiania dowolnego kodu, który musi zostać wykonany, nawet jeśli istnieje wyjątek. Kontrola jest zawsze przekazywana do bloku ostatecznie, niezależnie od tego, jak wychodzi blok try.
Ahh ... Myślę, że rozumiem, co mówisz! Zajęło mi to chwilę ... zastanawiasz się "dlaczego umieścić go w bloku na końcu zamiast po bloku w końcu i całkowicie poza try-catch-w końcu".
Na przykład może to być spowodowane tym, że wstrzymujesz wykonywanie, jeśli zgłosisz błąd, ale nadal chcesz wyczyścić zasoby, takie jak otwarte pliki, połączenia z bazą danych itp.
Kontrolny przepływ ostatniego bloku następuje po bloku Try lub Catch.
[1. First Code]
[2. Try]
[3. Catch]
[4. Finally]
[5. After Code]
z wyjątkiem 1> 2> 3> 4> 5, jeśli 3 ma instrukcję Return 1> 2> 3> 4
bez wyjątku 1> 2> 4> 5, jeśli 2 ma instrukcję return 1> 2> 4
Jak wspomniano w dokumentacji :
Powszechnym użyciem catch i wreszcie razem jest uzyskanie i wykorzystanie zasobów w bloku try, poradzenie sobie z wyjątkowymi okolicznościami w bloku catch i uwolnienie zasobów w bloku last.
Warto również przeczytać to , co stanowi:
Po znalezieniu pasującej klauzuli catch system przygotowuje się do przeniesienia kontroli do pierwszej instrukcji klauzuli catch. Przed rozpoczęciem wykonywania klauzuli catch system najpierw wykonuje kolejno wszystkie klauzule ostatecznie powiązane z instrukcjami try bardziej zagnieżdżonymi niż te, które wychwyciły wyjątek.
Jest więc jasne, że kod znajdujący się w finally
klauzuli zostanie wykonany, nawet jeśli poprzednia catch
klauzula zawierała return
instrukcję.