Istnieje kilka postów, które pytają, jaka jest już różnica między tymi dwoma.
(dlaczego muszę nawet o tym wspominać ...)
Ale moje pytanie jest inne, ponieważ nazywam „rzut ex” inną metodą podobną do boga .
public class Program {
public static void Main(string[] args) {
try {
// something
} catch (Exception ex) {
HandleException(ex);
}
}
private static void HandleException(Exception ex) {
if (ex is ThreadAbortException) {
// ignore then,
return;
}
if (ex is ArgumentOutOfRangeException) {
// Log then,
throw ex;
}
if (ex is InvalidOperationException) {
// Show message then,
throw ex;
}
// and so on.
}
}
Gdyby try & catch
zostały użyte w Main
, wtedy throw;
użyłbym do ponownego zwrócenia błędu. Ale w powyższym uproszczonym kodzie przechodzą wszystkie wyjątkiHandleException
Czy throw ex;
ma taki sam efekt jak dzwonienie, throw
gdy jest wywoływany w środku HandleException
?
c#
.net
exception
exception-handling
dance2die
źródło
źródło
Odpowiedzi:
Tak, jest różnica;
throw ex
resetuje ślad stosu (aby Twoje błędy mogły się wydawaćHandleException
)throw
nie robi - pierwotny przestępca zostałby zachowany.źródło
(Napisałem wcześniej, a @Marc Gravell mnie poprawił)
Oto przykład różnicy:
a oto wynik:
Widać, że w wyjątku 1 ślad stosu wraca do
DivByZero()
metody, podczas gdy w wyjątku 2 tak nie jest.Zwróć jednak uwagę, że numer wiersza pokazany w
ThrowException1()
iThrowException2()
jest numerem wierszathrow
instrukcji, a nie numerem wiersza połączeniaDivByZero()
, co prawdopodobnie ma sens teraz, gdy trochę o tym myślę ...Wyjście w trybie zwolnienia
Wyjątek 1:
Wyjątek 2:
Czy zachowuje oryginalny stackTrace tylko w trybie debugowania?
źródło
DevideByZero
, więc śledzenie stosu jest takie samo. może powinieneś zamieścić to jako własne pytaniePozostałe odpowiedzi są całkowicie poprawne, ale myślę, że ta odpowiedź zawiera dodatkowe szczegóły.
Rozważ ten przykład:
Jeśli usuniesz komentarz z
throw arithExc;
wiersza, wynikiem będzie:Z pewnością utraciłeś informacje o tym, gdzie zdarzył się ten wyjątek. Jeśli zamiast tego użyjesz
throw;
linii, otrzymasz:Jest to o wiele lepsze, ponieważ teraz widzisz, że była to
Program.Div
metoda, która spowodowała problemy. Ale nadal trudno jest sprawdzić, czy ten problem pochodzi z linii 35 czy linii 37 wtry
bloku.Jeśli użyjesz trzeciej alternatywy, zawierającej zewnętrzny wyjątek, nie stracisz żadnych informacji:
W szczególności widać, że to linia 35 prowadzi do problemu. Wymaga to jednak od ludzi przeszukiwania
InnerException
i używanie pośrednich wyjątków w prostych przypadkach wydaje się nieco pośrednie.W tym wpisie na blogu zachowują numer linii (wiersz bloku try), wywołując (poprzez odbicie)
internal
metodę intencjiInternalPreserveStackTrace()
naException
obiekcie. Ale nie jest miło używać takiego odbicia (.NET Framework możeinternal
pewnego dnia zmienić członków bez ostrzeżenia).źródło
zrozumiemy różnicę między rzutem a rzutem ex. Słyszałem, że w wielu wywiadach .net pytany jest ten często zadawany.
Aby przedstawić przegląd tych dwóch terminów, rzut i rzut ex służą zarówno do zrozumienia, gdzie wystąpił wyjątek. Rzut ex przepisuje ślad stosu wyjątku bez względu na to, gdzie rzeczywiście został zgłoszony.
Rozumiem na przykładzie.
Rozumiem pierwszy rzut.
wynik powyższego jest poniżej.
pokazuje pełną hierarchię i nazwę metody, w której faktycznie zgłoszono wyjątek. Jest to M2 -> M2. wraz z numerami linii
Po drugie .. pozwala zrozumieć przez rzut ex. Wystarczy zamienić rzut na rzut ex w bloku catch metody M2. jak poniżej.
kod wyjściowy rzutu ex jest taki jak poniżej.
Możesz zobaczyć różnicę w wynikach. Rzut ex po prostu ignoruje całą poprzednią hierarchię i resetuje śledzenie stosu za pomocą linii / metody, w której zapisywany jest rzut ex.
źródło
Kiedy to zrobisz
throw ex
, ten zgłoszony wyjątek staje się „oryginalny”. Tak więc nie będzie tam wszystkich poprzednich śladów stosu.Jeśli to zrobisz
throw
, wyjątek po prostu pójdzie wzdłuż linii, a otrzymasz pełny ślad stosu.źródło
Nie, spowoduje to, że wyjątek będzie miał inny ślad stosu. Tylko użycie
throw
wcatch
module obsługi obiektu bez wyjątku pozostawi ślad stosu bez zmian.Możesz zwrócić wartość logiczną z HandleException, niezależnie od tego, czy wyjątek zostanie ponownie wygenerowany, czy nie.
źródło
MSDN oznacza :
źródło
Spójrz tutaj: http://blog-mstechnology.blogspot.de/2010/06/throw-vs-throw-ex.html
Rzut :
Zachowuje informacje o stosie z wyjątkiem
Nazywa się to „Rethrow”
Jeśli chcesz zgłosić nowy wyjątek,
Rzuć Ex :
Nie będzie wysyłał informacji o stosie z wyjątkiem
Nazywa się to „Breaking the Stack”
Jeśli chcesz zgłosić nowy wyjątek,
źródło
Aby dać ci inną perspektywę, użycie rzucania jest szczególnie przydatne, jeśli udostępniasz interfejs API klientowi i chcesz podać szczegółowe informacje o stosie śledzenia dla swojej biblioteki wewnętrznej. Korzystając z rzutu tutaj, otrzymam ślad stosu w tym przypadku biblioteki System.IO.File dla File.Delete. Jeśli użyję throw ex, informacje te nie zostaną przekazane mojemu handlerowi.
źródło
jeśli wszystkie linie 1, 2 i 3 są skomentowane - Wyjście - wewnętrzna ex
jeśli wszystkie wiersze 2 i 3 są skomentowane - Wyjście - wewnętrzny ex System.DevideByZeroException: {"Próbowano podzielić przez zero."} ---------
jeśli wszystkie wiersze 1 i 2 są skomentowane - Wyjście - wewnętrzny ex System. Wyjątek: dzielenie przez 0 ----
jeśli wszystkie wiersze 1 i 3 są skomentowane - Wyjście - wewnętrzny ex System.DevideByZeroException: {"Próbowano podzielić przez zero."} ---------
i StackTrace zostanie zresetowany w przypadku wyrzucenia ex;
źródło