2013-08-11 10 views
6

Jaka jest różnica między Catch(Exception) a Catch(Exception ex). Widzę, że obaj dają mi oczekiwane wyniki. Więc jaka jest rzeczywista różnica? Który z nich jest zalecany?Różnica między połowem (wyjątek) a połowem (wyjątek ex)

Załóżmy, że kod znajduje się poniżej.

int a = 1, b = 0; 
try 
{ 
    int c = a/b; 
    Console.WriteLine(c); 
} 

Który z poniższych bloków catch jest zalecany do użycia? Jaka jest rzeczywista różnica między nimi?

catch (Exception ex) 
{ 
    Console.WriteLine(ex.Message); 
} 

LUB

catch (Exception) 
{ 
    Console.WriteLine("Oh NO!!"); 
} 
+0

Jeżeli nie jesteś zainteresowany tym, co ty połowu wyjątek (info na stosie, wiadomości itp) można po prostu napisać 'catch {Console.WriteLine (" Oh No ");}' – Steve

+1

Różnica polega na tym, że masz * jakiś * pomysł, dlaczego twój program przestanie działać poprawnie w pierwszym fragmencie. Brak w drugim fragmencie. Drugi sposób sprawia, że ​​użytkownicy SO zadają pytania typu "to nie działa, wystąpił błąd". Po prostu nie pisz w ten sposób. –

+1

@Steve Istnieje niewielka różnica między 'catch' i' catch (Exception) '. Pierwszy będzie przechwytywał wszystkie obiekty wyjątku, drugi przechwytuje tylko obiekty wyjątków pochodzące z 'Exception'. W języku C# można tylko rzucać obiektami pochodzącymi od 'Exception', ale CLR obsługuje więcej. – user1908061

Odpowiedz

3

No catch(Exception ex) jest tak samo jak catch(Exception) z jedną różnicą tylko: w catch(Exception ex) mamy dostęp do tej klasy wyjątku (błąd przyczyny) instancji. Zazwyczaj trzeba instancję klasy wyjątek wydrukować oryginalny wiadomość:

try { 
    ... 
    } 
    catch (AppServerException e) { 
    Console.WriteLine("Application server failed to get data with the message:"); 
    Console.WriteLine(e.Message); // <- What's actually got wrong with it 
    } 

Jeśli nie potrzebujemy wyjątku instancję klasy, na przykład planujecie tylko zużywają wyjątek , haczyk (Exception ex) składnia jest nadmierna i catch (Exception) jest prefferable:

try { 
    c = a/b; 
    } 
    catch (DivideByZeroException) { 
    c = Int.MaxValue; // <- in case b = 0, let c be the maximum possible int 
    } 

końcu. Nie złapać ogólną klasę Exception bez ponownego throughing:

try { 
    int c = a/b; 
    } 
    catch (Exception) { // <- Never ever do this! 
    Console.WriteLine("Oh NO!!"); 
    } 

naprawdę chcesz kodować „cokolwiek błąd (zielony opar z CPU zestawie) miał stało tylko wydrukować«Oh No»i dalej”? Wzór z klasy Exception jest coś takiego:

tran.Start(); 

    try { 
    ... 
    tran.Commit(); 
    } 
    catch (Exception) { 
    // Whatever had happened, let's first rollback the database transaction 
    tran.Rollback(); 

    Console.WriteLine("Oh NO!"); 

    throw; // <- re-throw the exception 
    } 
+1

Nie zgadzam się z "_Nie przechwytuj ogólnej klasy Wyjątek bez ponownego rzucania'_. i "Czy naprawdę chcesz zakodować" jakikolwiek błąd ", po prostu wydrukuj" O nie "i kontynuuj?". 1.Czasem robię 2. Są inne rzeczy, które chcę robić (poza rejestrowaniem). Powszechne jest wychwytywanie 'Exception ex' w kodzie. – mayu

+0

Jest to "DivideByZeroException", a nie "ZeroDivisonException" afaik. – mayu

3

To bardzo proste:

  • w pierwszym kodzie, można złapać wyjątek i uzyskać obiekt reprezentujący go, dzięki czemu można uzyskać więcej informacji na temat co się stało
  • w drugim kodzie, wiesz tylko, że wyjątek został podniesiony, ale nie masz więcej informacji na ten temat.

To, czego należy używać, zależy od tego, ile informacji chcesz uzyskać o zgłoszonym wyjątku.

2

Jeśli potrzebujesz użyć wyjątku wewnątrz bloku catch, podaj Exception imię; w przeciwnym razie zachowaj to anonimowo.

Istnieją sytuacje, w których blok catch musi zrobić coś więcej niż po prostu pokazać komunikat wyjątku. Na przykład, gdy przechwycisz wyjątki specyficzne dla aplikacji, możesz być w stanie zbadać dodatkowe elementy obiektu wyjątku. Oto hipotetyczny przykład:

catch (ConnectToServerException cse) { 
    MessageBox.Show(string.Format(
     "Connection to server '{0}' failed. Use a name from the following list: {1}" 
    , cse.AttemptedConnectionServerName 
    , string.Join(", ", cse.AllowedServerNames) 
    )); 
} 

Powyższy kod zakłada, że ​​zwyczaj wyjątek ConnectToServerException ma właściwość o nazwie AttemptedConnectionServerName z nazwą serwera, do którego próbował się połączyć, a właściwość wyliczania AllowedServerNames z nazwiskami dostępna serwery.

Istnieją również sytuacje, w których należy tylko wiedzieć, że nastąpił wyjątek określonego typu. W tym przypadku nie musisz podawać dla niego nazwanej zmiennej.

0

Catch (Exception) zrobić to samo, ponieważ jest to również typ Exception.

Catch (Exception ex) przechwytuje wszystkie wyjątki, a ponadto można pobrać wiadomość poprzez jej odwołanie.

Użycie jest zależne od wymagań, jeśli chcesz pokazać komunikat wyjątku, masz obiekt do użyciaw przeciwnym razie wystarczy Catch (Exception).

0

Z catch(Exception) tylko określić, jakiego rodzaju wyjątku będziesz uchwyt w tym bloku catch (w tym przypadku, każdy wyjątek, który jest podniesiony, więc byłoby tak samo jak tylko catch)

Z catch(Exception ex) ty przekazać instancję rzeczywistego wyjątku, który jest wywoływany, aby uzyskać dostęp do właściwości wyjątku i zrobić coś za pomocą dostarczonych informacji.

0

Różnica polega na tym, że wydrukuje się Próbowano podzielić przez zero. a drugi wydrukuje Oh NO !!.

Obsługa wyjątków jest problemem złożonym i zależy od zastosowania, ale oto kilka ogólnych uwag:


Generalnie to najlepiej, aby zapewnić teleskopowe dla wyjątkami:

coś takiego:

catch ({System.DivideByZeroException ex) 
{ 
    Console.WriteLine("Ops. I cannot divide by zero."); 
} 
catch ({System.Exception ex) 
{ 
    Console.WriteLine("There was an error during calculations: {0}", ex.Message); 
} 

Wcześniej czy później dowiesz się hat Console.WriteLine jest po prostu niewystarczająco dobry i będziesz musiał użyć rejestratora najlepiej, aby zacząć go używać wcześniej.


Idealnie, jeśli zdecydujesz się wystawiać surowych komunikatów o błędach do użytkownika, powinno być drukowanie wszystkich wiadomości w łańcuchu wyjątków lub przynajmniej ten, który jest najbardziej głębokie.

Coś jak:

catch ({System.DivideByZeroException ex) 
{ 
    Console.WriteLine("Oops. I cannot divide by zero."); 
} 
catch ({System.Exception ex) 
{ 
    Console.WriteLine(GetExceptionMsgs(ex)); 
} 

...in another class... 
public static string GetExceptionMsgs(Exception ex) { 
    if(ex == null) { 
     return "No exception = no details"; 
    } 
    var sb = new StringBuilder(); 
    while(ex != null) { 
     sb.AppendLine(ex.Message); 
     ex = ex.InnerException; 
    } 
    return sb.ToString() 
} 
Powiązane problemy