Poniższy kod będzie narzekał
try
{
session.Save(obj);
return true;
}
catch (Exception e)
{
throw e;
return false; // this will be flagged as unreachable code
}
to nie będzie:
try
{
session.Save(obj);
return true;
}
catch (Exception e)
{
return false;
throw e;
}
Nie rozumiem ... Myślałem, że mój csc101 powiedział mi, że instrukcje return powinny zawsze być ostatnim stwierdzeniem funkcji i że wychodzi z funkcji i zwraca kontrolę do kodu wywołującego. Dlaczego jest to sprzeczne z logiką mojego profesora i dlaczego tylko jedno z nich generuje ostrzeżenie?
return
opuści metodę; throw
będzie również wyjdź z tej metody, zakładając, że nie ma jej w środku try
. Może wyjść tylko raz!
Tak więc niezależnie od kolejności - pierwszy z throw
/ return
skutecznie zakończyć metodę.
Jednak bardziej ogólna informacja zwrotna: jeśli celem jest zwrócenie błędu po niepowodzeniu, wystarczy:
try
{
session.Save(obj);
return true;
}
catch
{
return false;
}
Osobiście powiedziałbym, że jest to zły kod - ukrywa on rzeczywisty problem od wywołującego, co bardzo utrudnia debugowanie. Nic nam to nie mówi czemu nie powiodło się. Powiedziałbym, że lepszym rozwiązaniem jest po prostu pozwól bańce wyjątków. W takim przypadku nie ma sensu powracać true
, ponieważ nigdy nie wrócimy false
- i nie ma sensu chwytanie wyjątku tylko po to, żeby go ponownie rzucić. Tak więc cała metoda staje się:
session.Save(obj);
(nic więcej nie jest wymagane)
Jeśli twoje pytanie brzmi "dlaczego tylko jedno z nich generuje ostrzeżenie": sprawiedliwe pytanie, ale kompilator nie jest wymagany zauważyć zarówno z nich dla ciebie. Być może powinien to zauważyć. ja posądzać że gmcs
by zauważ to i ostrzegaj - kompilator w mono jest o wiele bardziej skłonny wskazać głupotę.
Edytuj: zgodnie z oczekiwaniami, [g] mcs wyjścia:
Program.cs(15,13): warning CS0162: Unreachable code detected
Program.cs(28,13): warning CS0162: Unreachable code detected
dla kodu poniżej - tak więc rzeczywiście zgłasza oba zastosowania jako ostrzeżenia:
class Program
{
static void Main() { }
static void DoSomething() { }
bool ReturnFirst()
{
try
{
DoSomething();
return true;
}
catch
{
return false;
throw; // line 15
}
}
bool ThrowFirst()
{
try
{
DoSomething();
return true;
}
catch
{
throw;
return false; // line 28
}
}
}
Mylisz się: obie twoje przykłady podnoszą Martwy kod błąd kompilatora, ponieważ oba throw
i return
oznacz punkt wyjścia metody, a poza tym punktem nie jest dozwolony żaden inny kod.
Niezależnie od tego, czy kompilator na to pozwala, czy nie, kod poniżej albo throw
albo return
jest nadal martwy i nigdy nie będzie miał szansy na wykonanie.
(UWAGA: to pytanie zostało początkowo oznaczone jako Java, a moje pierwsze zdanie dotyczy semantyki kompilatora Java)
Ponieważ jakikolwiek kod po instrukcji return w bloku kodu będzie nieosiągalny.
Ta odpowiedź jest oparta na języku C # i może lub nie może być stosowana w Javie.
W takim przypadku faktycznie nie potrzebujesz return
komunikat. throw
będzie ostatnim krokiem funkcji.
W tym przykładzie oba return
i throw
zakończy bieżącą funkcję. Bez względu na to, w którą stronę się je znajduje, najpierw zawsze zapobiegnie osiągnięciu drugiego.
UWAGA: Wyjątek od kiedy throw
oświadczenie zakończyłoby funkcję, gdyby miało być opakowane w try
blok. W tym przypadku throw
funkcja zakończy działanie pozostałych try
kod bloku i przejdź do najbardziej odpowiedniego catch
blok - lub finally
blokować, jeśli a catch
nie ma zastosowania.
Twój kod powinien wyglądać tak:
try
{
session.Save(obj);
return true;
}
catch(Exception e)
{
throw e;
}
Jednak nie ma sensu, aby spróbować / złapać, jeśli wszystko, co robisz, to ponowne rzucanie wyjątku.
Aby odpowiedzieć na Twoje jedyne pytanie:
Dlaczego to niweczy logikę mojego profesora?
Cóż albo twój profesor się myli, albo źle je zrozumiałeś
"Return false;" w bloku catch jest nieosiągalny z powodu "throw e;" tuż przed tym. Kiedy kod wykonuje się w bloku catch, pierwsza linia jest rzutem, co oznacza, że natychmiast rzucasz wyjątek do metody wywołującej, a zatem żaden poniższy kod nie zostanie wykonany.
try
{
session.Save(obj);
return true;
}
catch(Exception e)
{
throw e; //Throws exception to calling method
return false; //this will be flagged as unreachable code
}
Mam nadzieję, że to pomoże.