Pytanie Catch wielu wyjątków na raz?


Odradza się po prostu złapać System.Exception. Zamiast tego należy uchwycić tylko "znane" wyjątki.

To czasami prowadzi do niepotrzebnego powtarzalnego kodu, na przykład:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
    WebId = Guid.Empty;
}
catch (OverflowException)
{
    WebId = Guid.Empty;
}

Zastanawiam się: Czy istnieje sposób, aby uchwycić oba wyjątki i tylko zadzwonić WebId = Guid.Empty zadzwonić raz?

Podany przykład jest raczej prosty, ponieważ jest tylko a GUID. Ale wyobraź sobie kod, w którym wielokrotnie modyfikujesz obiekt, a jeśli jedna z manipulacji zawodzi w oczekiwany sposób, chcesz "zresetować" object. Jeśli jednak wystąpi nieoczekiwany wyjątek, nadal chcę go wyrzucić wyżej.


1712
2017-09-25 20:56


pochodzenie


Jeśli korzystasz z .net 4 lub nowszego, wolę używać agregacji wyjątków msdn.microsoft.com/en-us/library/system.aggregateexception.aspx - Bepenfriends
Bepenfriends- Od System.Guid nie rzuca Wyjątek AggregateExceptionByłoby wspaniale, gdybyś Ty (lub ktoś) umieścił odpowiedź pokazującą, w jaki sposób zostałbyś opakowany w wyjątek AggregateException itp. - weir
Podczas korzystania AggregateException: Zgłaszanie wyjątku AggregateException w moim własnym kodzie - DavidRR
"Odradza się po prostu wychwycić wyjątek System.Exception." i czy metoda może rzucić 32 typy wyjątków, co zrobić? pisać catch dla każdego z nich osobno? - giorgi.m
Zachowaj to tak, jak to masz. Przenieś kod do obsługi błędów, jeśli chcesz, aby był tylko jeden wiersz na instrukcję catch. - rolls


Odpowiedzi:


Łapać System.Exception i włącz typy

catch (Exception ex)            
{                
    if (ex is FormatException || ex is OverflowException)
    {
        WebId = Guid.Empty;
        return;
    }

    throw;
}

1792
2017-09-25 21:01



Niestety, FxCop (tj. - Visual Studio Code Analysis) nie podoba się, gdy złapiesz wyjątek. - Andrew Garrison
Zgadzam się z tym, że nie łapię wyjątku, ale w tym przypadku połów jest filtrem. Możesz mieć warstwę wyższą, która będzie obsługiwać inne typy wyjątków. Powiedziałbym, że to jest poprawne, nawet jeśli zawiera ono catch (wyjątek x). Nie modyfikuje to przepływu programu, obsługuje tylko pewne wyjątki, pozwala pozostałej aplikacji zajmować się dowolnymi innymi typami wyjątków. - lkg
Najnowsza wersja FxCop nie zgłasza wyjątku w przypadku użycia powyższego kodu. - Peter
Nie jestem pewien, co było nie tak z kodem PO. Przyjęta # 1 odpowiedź to prawie dwa razy więcej linii i znacznie mniej czytelna. - João Bragança
@ JoãoBragança: Podczas gdy ta odpowiedź w tym przykładzie używa więcej linii, spróbuj sobie wyobrazić, jeśli masz do czynienia z plikiem IO na przykład, a wszystko, co chcesz zrobić, to wychwycić te wyjątki i zrobić kilka komunikatów dziennika, ale tylko te, które oczekujesz od twojego file Metody IO. Wtedy często masz do czynienia z większą liczbą (około 5 lub więcej) różnych typów wyjątków. W tej sytuacji to podejście może zaoszczędzić ci trochę linii. - Xilconic


EDYTOWAĆ: Zgadzam się z innymi, którzy twierdzą, że od C # 6.0, filtry wyjątków są teraz idealnym rozwiązaniem: catch (Exception ex) when (ex is ... || ex is ... )

Tyle, że nadal nienawidzę jednokierunkowego układu i osobiście zgłaszałem kod jak poniżej. Uważam, że jest tak funkcjonalny, jak estetyczny, ponieważ uważam, że poprawia zrozumienie. Niektórzy mogą się nie zgodzić:

catch (Exception ex) when (
    ex is ...
    || ex is ...
    || ex is ...
)

ORYGINALNY:

Wiem, że trochę się spóźniłem na przyjęcie, ale święty dym ...

Cięcie prosto do pościgu, ten rodzaj duplikacji wcześniejszej odpowiedzi, ale jeśli naprawdę chcesz wykonać wspólną akcję dla kilku typów wyjątków i zachować wszystko czyste i schludne w ramach jednej metody, dlaczego nie po prostu użyć lambda / closure / inline function do zrobienia czegoś takiego jak poniżej? Chodzi mi o to, że szanse są całkiem dobre, że w końcu zdasz sobie sprawę, że chcesz, aby to zamknięcie było osobną metodą, którą możesz wykorzystać w każdym miejscu. Ale wtedy będzie to bardzo łatwe, bez faktycznej zmiany strukturalnej reszty kodu. Dobrze?

private void TestMethod ()
{
    Action<Exception> errorHandler = ( ex ) => {
        // write to a log, whatever...
    };

    try
    {
        // try some stuff
    }
    catch ( FormatException  ex ) { errorHandler ( ex ); }
    catch ( OverflowException ex ) { errorHandler ( ex ); }
    catch ( ArgumentNullException ex ) { errorHandler ( ex ); }
}

Nie mogę pomóc, ale zastanawiam się (ostrzeżenie: trochę ironii / sarkazmu) dlaczego, do licha, staraj się, aby po prostu zastąpić:

try
{
    // try some stuff
}
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}

... z pewną zwariowaną wersją tego następnego kodu, mam na myśli przykład, tylko po to, by udawać, że zapisujesz kilka klawiszy.

// sorta sucks, let's be honest...
try
{
    // try some stuff
}
catch( Exception ex )
{
    if (ex is FormatException ||
        ex is OverflowException ||
        ex is ArgumentNullException)
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

Ponieważ z pewnością nie jest automatycznie bardziej czytelny.

Oczywiście, opuściłem trzy identyczne przypadki /* write to a log, whatever... */ return; z pierwszego przykładu.

Ale o to mi chodzi. Słyszeliście o funkcjach / metodach, prawda? Poważnie. Napisz często ErrorHandler i wywołaj go z każdego bloku catch.

Jeśli pytasz mnie, drugi przykład (z if i is słowa kluczowe) jest znacznie mniej czytelna, a jednocześnie znacznie bardziej podatna na błędy podczas fazy konserwacji projektu.

Faza utrzymania, dla każdego, kto może być stosunkowo nowy w programowaniu, będzie obejmowała 98,7% lub więcej całkowitego czasu trwania twojego projektu, a biedny Schmuck przeprowadzający konserwację prawie na pewno będzie kimś innym niż ty. I jest bardzo duża szansa, że ​​spędzą 50% swojego czasu na pracy przeklinając twoje imię.

I oczywiście FxCop szczeka na ciebie, więc musisz równieżdodaj atrybut do kodu, który ma dokładnie zip do działania z uruchomionym programem, i jest tam tylko po to, aby poinformować FxCop, aby zignorował problem, który w 99,9% przypadków jest całkowicie poprawny w oznaczaniu. I, przepraszam, mogę się mylić, ale czy ten atrybut "ignoruj" nie jest faktycznie wkompilowany w twoją aplikację?

Położyłby cały if test na jednej linii sprawia, że ​​jest on bardziej czytelny? Nie sądzę. Mam na myśli, że inny programista gwałtownie argumentował kiedyś, że umieszczenie więcej kodu w jednej linii sprawi, że "będzie działał szybciej". Ale oczywiście był szalenie szalony. Próbując wyjaśnić mu (z prostą twarzą - co stanowiło wyzwanie), w jaki sposób interpreter lub kompilator podzieliłoby tę długą linię na osobne instrukcje jedno-instrukcje-na-linii - w zasadzie identyczne z wynikiem, gdyby poszedł i po prostu sprawił, że kod był czytelny, zamiast próbować sprytnie kompilatora - nie miał na niego żadnego wpływu. Ale dygresję.

Ile mniej Czy można to odczytać, gdy dodaje się trzy dodatkowe typy wyjątków, miesiąc lub dwa od teraz? (Odpowiedź: dostaje a los mniej czytelne).

Jedną z głównych kwestii jest to, że większość kwestii związanych z formatowaniem tekstowego kodu źródłowego, nad którym wszyscy patrzymy każdego dnia, to uczynienie go naprawdę, naprawdę oczywistym dla innych ludzi, co faktycznie dzieje się podczas działania kodu. Ponieważ kompilator zamienia kod źródłowy na coś zupełnie innego i nie obchodzi go twój styl formatowania kodu. Więc wszystko w jednym rzędzie całkowicie też jest do bani.

Tylko mówię...

// super sucks...
catch( Exception ex )
{
    if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
    {
        // write to a log, whatever...
        return;
    }
    throw;
}

370
2017-10-12 00:24



Kiedy po raz pierwszy natknąłem się na to pytanie, byłem po całej zaakceptowanej odpowiedzi. Fajnie, po prostu łapię wszystko Exceptions i sprawdź typ. Myślałem, że to wyczyściło kod, ale coś powstrzymywało mnie przed powrotem do tego pytania i rzeczywiście przeczytałem inne odpowiedzi na to pytanie. Przygryzłem to przez chwilę, ale muszę się z tobą zgodzić. To jest jeszcze czytelny i obsługiwany, aby użyć funkcji do wyschnięcia kodu, aby wszystko złapać, sprawdź typ porównując z listą, zawijając kod i rzucając. Dziękuję za spóźnienie i zapewnienie opcji alternatywnej i rozsądnej (IMO). +1. - erroric
Używanie funkcji obsługi błędów nie działałoby, gdybyś chciał dołączyć throw;. Powinieneś powtórzyć ten wiersz kodu w każdym bloku catch (oczywiście nie koniec świata, ale warto wspomnieć, ponieważ jest to kod, który musiałby zostać powtórzony). - kad81
@ kad81, to prawda, ale nadal dostaniesz korzyść z pisania kodu logowania i oczyszczania w jednym miejscu i zmieniania go w jednym miejscu, jeśli zajdzie taka potrzeba, bez głupiej semantyki przechwytywania podstawowego typu wyjątku, a następnie rozgałęzienia opartego na typ wyjątku. I ten dodatkowy throw(); oświadczenie w każdym bloku catch to niewielka cena do zapłacenia, IMO, i nadal pozostawia cię w pozycji do wykonania dodatkowego czyszczenia specyficznego dla wyjątku, jeśli to konieczne. - Craig
Cześć @Reitffunk, po prostu użyj Func<Exception, MyEnumType> zamiast Action<Exception>. Jest to Func<T, Result>, z Result jest typem zwrotu. - Craig
Jestem tutaj w całkowitej zgodzie. Ja też przeczytałem pierwszą odpowiedź, a myśl wydaje się logiczna. Przeniesiono do ogólnej wartości 1 dla wszystkich procedur obsługi wyjątków. Coś we mnie sprawiło, że wewnętrznie wymiotowałem ... więc przywróciłem kod. Potem natknąłem się na tę piękność! To wymagania być przyjętą odpowiedzią - Conor Gallagher


Jak zauważyli inni, możesz mieć if oświadczenie wewnątrz twojego bloku catch, aby określić, co się dzieje. C # 6 obsługuje filtry wyjątków, więc następujące czynności będą działać:

try { … }
catch (Exception e) when (MyFilter(e))
{
    …
}

The MyFilter metoda może wtedy wyglądać mniej więcej tak:

private bool MyFilter(Exception e)
{
  return e is ArgumentNullException || e is FormatException;
}

Alternatywnie, można to wszystko zrobić inline (prawa strona instrukcji when musi być po prostu wyrażeniem boolowskim).

try { … }
catch (Exception e) when (e is ArgumentNullException || e is FormatException)
{
    …
}

Różni się to od używania if oświadczenie z wewnątrz catch blokuj, używając filtrów wyjątków nie będzie rozwiń stos.

Możesz pobrać Visual Studio 2015 żeby to sprawdzić.

Jeśli chcesz kontynuować korzystanie z Visual Studio 2013, możesz zainstalować następujący pakiet nuget:

Zainstaluj pakiet Microsoft.Net.Compilers

W chwili pisania tego tekstu będzie to obejmować wsparcie dla C # 6.

Odwołanie do tego pakietu spowoduje, że projekt zostanie zbudowany przy użyciu   konkretna wersja kompilatorów C # i Visual Basic zawartych w   pakiet, w przeciwieństwie do każdej zainstalowanej wersji systemu.


241
2018-04-04 13:59



Cierpliwie czekam na oficjalne wydanie 6 ... Chciałbym zobaczyć, jak to się dzieje, kiedy to się stanie. - RubberDuck
@RubberDuck Umiera dla operatora propagacji zerowej z C # 6. Próbuję przekonać resztę mojego zespołu, że ryzyko niestabilnego języka / kompilatora jest tego warte. Mnóstwo drobnych usprawnień o ogromnym wpływie. Jeśli chodzi o oznaczanie jako odpowiedź, nieważne, o ile ludzie zdają sobie sprawę, że to jest możliwe, jestem szczęśliwy. - Joe
Dobrze?! Przyjrzę się dobrze mojej bazie kodu w najbliższej przyszłości. =) Wiem, że czek nie jest ważny, ale biorąc pod uwagę zaakceptowaną odpowiedź wkrótce będzie nieaktualny, mam nadzieję, że OP wróci, aby to sprawdzić, aby nadać mu odpowiednią widoczność. - RubberDuck
Po części dlatego nie przyznałem tego jeszcze @Joe. Chcę, żeby to było widoczne. Możesz jednak dodać przykład wbudowanego filtru dla większej przejrzystości. - RubberDuck


Nie w C # niestety, ponieważ do tego celu potrzebny jest filtr wyjątków, a C # nie ujawnia tej funkcji MSIL. VB.NET ma jednak taką możliwość, np.

Catch ex As Exception When TypeOf ex Is FormatException OrElse TypeOf ex Is OverflowException

Możesz użyć anonimowej funkcji do enkapsulacji swojego kodu błędu, a następnie wywołać go w tych konkretnych blokach catch:

Action onError = () => WebId = Guid.Empty;
try
{
    // something
}
catch (FormatException)
{
    onError();
}
catch (OverflowException)
{
    onError();
}

184
2017-09-25 21:03



Ciekawy pomysł i kolejny przykład, że VB.net ma czasem pewne interesujące zalety w porównaniu z C # - Michael Stum♦
@MichaelStum z że rodzaj składni trudno nazwać to w ogóle interesującym ... dreszcz - MarioDS
Filtry wyjątków nadchodzą w c # 6! Zauważ różnicę w używaniu filtrów na korzyść ponownego rzucania roslyn.codeplex.com/discussions/541301 - Arne Deruwe
@ArneDeruwe Dziękuję za ten link! Właśnie nauczyłem się jednego ważniejszego powodu, aby nie rzucać ponownie: throw e; niszczy stos śledzenia i callstack, throw; niszczy "tylko" stację wywoławczą (renderowanie zrzutu awaryjnego jest bezużyteczne!) bardzo dobry powód, aby nie używać żadnego, jeśli można tego uniknąć! - AnorZaken
Jeśli się nie mylę, możesz również przechwycić przechwycenie w VB, tak jak możesz, za pomocą instrukcji case lub (switch in c #), Try Catch ex As ArgumentException Catch ex As NullReferenceException End Try Ale niestety C # tak nie jest, że zostaliśmy z pomocą metody pomocniczej lub złapać generycznie i określić typ. - David Carrigan


Ze względu na kompletność, od .NET 4.0kod może zostać przepisany jako:

Guid.TryParse(queryString["web"], out WebId);

TryParse nigdy nie wyrzuca wyjątków i zwraca wartość false, jeśli format jest nieprawidłowy, ustawienie WebId na Guid.Empty.


Od C # 7 możesz uniknąć wprowadzania zmiennej w osobnym wierszu:

Guid.TryParse(queryString["web"], out Guid webId);

Możesz także tworzyć metody parsowania zwracanych krotek, które nie są dostępne w .NET Framework, ale od wersji 4.6:

(bool success, Guid result) TryParseGuid(string input) =>
    (Guid.TryParse(input, out Guid result), result);

I użyj ich tak:

WebId = TryParseGuid(queryString["web"]).result;
// or
var tuple = TryParseGuid(queryString["web"]);
WebId = tuple.success ? tuple.result : DefaultWebId;

Następna bezużyteczna aktualizacja tej bezużytecznej odpowiedzi pojawia się, gdy dekonstrukcja out-parametrów jest zaimplementowana w C # 12. :)


123
2018-04-13 12:18



Precyzyjnie - zwięźle i całkowicie pomijasz karę za wykonanie wyjątku, złą formę celowego używania wyjątków do kontrolowania przepływu programu i delikatne skupianie się na logice konwersji, trochę tu i troszeczkę . - Craig
Wiem, co miałeś na myśli, ale oczywiście Guid.TryParse nigdy nie wraca Guid.Empty. Jeśli ciąg znaków ma niepoprawny format, ustawia on result parametr wyjściowy do Guid.Empty, ale to zwraca  false. Wspominam o tym, bo widziałem kod, który robi rzeczy w stylu Guid.TryParse(s, out guid); if (guid == Guid.Empty) { /* handle invalid s */ }, co zwykle jest złe, jeśli s może być reprezentacją ciągu znaków Guid.Empty. - hvd
wow, odpowiedziałeś na to pytanie, ale nie jest to zgodne z duchem pytania. Większy problem to coś innego :( - nawfal
Właściwy wzorzec korzystania z TryParse jest oczywiście bardziej podobny if( Guid.TryParse(s, out guid){ /* success! */ } else { /* handle invalid s */ }, co nie pozostawia wątpliwości, jak zepsuty przykład, w którym wartością wejściową może być w rzeczywistości ciąg znaków Guid. - Craig
Ta odpowiedź może rzeczywiście być poprawna w odniesieniu do Guid.Parse, ale pominęła cały punkt pierwotnego pytania. Co nie miało nic wspólnego z Guid.Parse, ale było w odniesieniu do przechwytywania wyjątku vs FormatException / OverflowException / etc. - Conor Gallagher


Jeśli możesz uaktualnić swoją aplikację do C # 6, masz szczęście. Nowa wersja C # zaimplementowała filtry wyjątków. Możesz napisać to:

catch (Exception ex) when (ex is FormatException || ex is OverflowException) {
    WebId = Guid.Empty;
}

Niektórzy uważają, że ten kod jest taki sam jak

catch (Exception ex) {                
    if (ex is FormatException || ex is OverflowException) {
        WebId = Guid.Empty;
    }
    throw;
}

Ale nie jest. W rzeczywistości jest to jedyna nowa funkcja w C # 6, której nie można emulować w poprzednich wersjach. Po pierwsze, ponowne rzucenie oznacza więcej narzutę niż pomijanie połowu. Po drugie, nie jest semantycznie równoważny. Nowa funkcja zachowuje nienaruszony stos podczas debugowania kodu. Bez tej funkcji zrzut awaryjny jest mniej użyteczny, a nawet bezużyteczny.

Zobacz dyskusja na ten temat na CodePlex. I przykład pokazujący różnicę.


62
2018-04-01 12:29



Rzut bez wyjątków zachowuje stos, ale "throw ex" nadpisze go. - Ivan


Jeśli nie chcesz korzystać z if oświadczenie w catch zakresy, w C# 6.0 możesz użyć Exception Filters składnia który był już obsługiwany przez CLR w wersjach podglądu, ale istniał tylko w VB.NET/MSIL:

try
{
    WebId = new Guid(queryString["web"]);
}
catch (Exception exception) when (exception is FormatException || ex is OverflowException)
{
    WebId = Guid.Empty;
}

Ten kod złapie Exception tylko wtedy, gdy jest InvalidDataException lub ArgumentNullException.

Właściwie możesz umieścić w nim praktycznie dowolny warunek when klauzula:

static int a = 8;

...

catch (Exception exception) when (exception is InvalidDataException && a == 8)
{
    Console.WriteLine("Catch");
}

Zauważ, że w przeciwieństwie do if oświadczenie wewnątrz catchzakres, Exception Filters nie mogę rzucić Exceptions, a kiedy to robią, lub gdy warunek nie jest true, Następny catch stan zostanie oceniony w zamian:

static int a = 7;

static int b = 0;

...

try
{
    throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
    Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
    Console.WriteLine("General catch");
}

Wyjście: Ogólny połów.

Kiedy jest więcej niż jeden true  Exception Filter - pierwszy zostanie przyjęty:

static int a = 8;

static int b = 4;

...

try
{
    throw new InvalidDataException();
}
catch (Exception exception) when (exception is InvalidDataException && a / b == 2)
{
    Console.WriteLine("Catch");
}
catch (Exception exception) when (exception is InvalidDataException || exception is ArgumentException)
{
    Console.WriteLine("General catch");
}

Wyjście: Złap.

I jak widać w MSIL kod nie jest przetłumaczony na if oświadczenia, ale do Filters, i Exceptions nie można wyrzucić z obszarów oznaczonych symbolem Filter 1 i Filter 2 ale filtr wyrzucając Exception zawiedzie, a ostatnia wartość porównania zostanie przesunięta na stos przed endfilter polecenie określi sukces / porażkę filtra (Catch 1  XOR  Catch 2 zostanie odpowiednio wykonany):

Exception Filters MSIL

Ponadto, konkretnie Guid zawiera Guid.TryParse metoda.


26
2017-10-07 17:31





Przyjęta odpowiedź wydaje się akceptowalna, z wyjątkiem tego, że CodeAnalysis /FxCop będzie narzekać na fakt, że łapie ogólny typ wyjątku.

Wydaje się również, że operator "jest" może nieco obniżyć wydajność.

CA1800: Nie należy niepotrzebnie rzucać mówi, aby "zamiast tego rozważyć testowanie wyniku operatora" jako ", ale jeśli to zrobisz, będziesz pisał więcej kodu, niż jeśli złapisz każdy wyjątek osobno.

Tak czy inaczej, oto co bym zrobił:

bool exThrown = false;

try
{
    // Something
}
catch (FormatException) {
    exThrown = true;
}
catch (OverflowException) {
    exThrown = true;
}

if (exThrown)
{
    // Something else
}

19
2017-07-30 17:09



Ale pamiętaj, że nie możesz ponownie wyrzucić wyjątku bez utraty śledzenia stosu, jeśli zrobisz to w ten sposób. (Zobacz komentarz Michaela Stuma do zaakceptowanej odpowiedzi) - René
Ten wzór można poprawić, przechowując wyjątek (proszę wybaczyć słabe formatowanie - nie mogę wymyślić, jak umieścić kod w komentarzach): Exception ex = null; spróbuj {// coś} złapać (FormatException e) {ex = e; } catch (OverflowException e) {ex = e; } if (ex! = null) {// coś innego i poradzić sobie z ex} - Jesse Weigert
@JesseWeigert: 1. Możesz użyć odsunięć, aby nadać fragment tekstu jednoprzestrzennej czcionce i jasnoszarym tle. 2. Nadal nie będziesz w stanie powtórzyć oryginalnego wyjątku w tym stacktrace. - Oliver
@CleverNeologism choć może być prawdą, że przy użyciu is Operator może mieć nieznaczny negatywny wpływ na wydajność, jest również prawdą, że obsługa wyjątków nie jest miejscem, w którym zbytnio zależy na optymalizacji wydajności. Jeśli Twoja aplikacja spędza tak dużo czasu w modułach obsługi wyjątków, że optymalizacja wydajności będzie miała znaczny wpływ na wydajność aplikacji, to istnieją inne problemy z kodem, na które trudno się przyjrzeć. Powiedziawszy to, nadal nie lubię tego rozwiązania, ponieważ tracisz ślad stosu i dlatego, że czyszczenie jest usuwane z kontekstu instrukcji catch. - Craig
Jedyny czas is Operator pogarsza wydajność, jeśli wykonasz później as operacja (stąd kwalifikują regułę przy pomocy niepotrzebnie). Jeśli wszystko, co robisz, to testowanie obsady bez faktycznego wykonywania obsady, a następnie is operator jest dokładnie tym, czego chcesz użyć. - saluce


Jest to wariant odpowiedzi Matta (uważam, że jest to nieco czystsze) ... użyj metody:

public void TryCatch(...)
{
    try
    {
       // something
       return;
    }
    catch (FormatException) {}
    catch (OverflowException) {}

    WebId = Guid.Empty;
}

Wszelkie inne wyjątki będą zgłaszane i kod WebId = Guid.Empty; nie zostanie trafiony. Jeśli nie chcesz, aby inne wyjątki powodowały awarię twojego programu, dodaj to po dwóch pozostałych połowach:

...
catch (Exception)
{
     // something, if anything
     return; // only need this if you follow the example I gave and put it all in a method
}

18
2017-08-31 20:51



-1 To zostanie wykonane WebId = Guid.Emtpy w przypadku, gdy nie został zgłoszony żaden wyjątek. - Sepster
@sepster Myślę, że deklaracja zwrotu po "// coś" jest tutaj zawarta. Nie podoba mi się to rozwiązanie, ale jest to konstruktywny wariant dyskusji. +1, aby cofnąć swój głos :-) - toong
@Sepster toong ma rację, założyłem, że gdybyś chciał tam wrócić, to umieściłbyś jeden ... Próbowałem uczynić moją odpowiedź wystarczająco ogólną, by zastosować ją do wszystkich sytuacji, na wypadek gdyby inni z podobnymi, ale nie dokładnymi dobrze. Jednak na dobrą sprawę dodałem returndo mojej odpowiedzi. Dzięki za wejście. - bsara


@Micheal

Lekko zmieniona wersja twojego kodu:

catch (Exception ex)
{
   Type exType = ex.GetType();
   if (exType == typeof(System.FormatException) || 
       exType == typeof(System.OverflowException)
   {
       WebId = Guid.Empty;
   } else {
      throw;
   }
}

Porównywanie ciągów jest brzydkie i powolne.


17
2017-09-25 21:01



Dlaczego nie użyć słowa kluczowego "is"? - Chris Pietschmann
@Michael - Jeśli Microsoft wprowadził, powiedzmy, StringTooLongException wywodzący się z FormatException, to nadal jest to wyjątek formatu, tylko jeden specyficzny. Zależy to od semantyki "catch this exact type" lub "catch exceptions", które oznaczają, że format łańcucha był nieprawidłowy ". - Greg Beech
@Michael - Zwróć też uwagę, że "catch (FormatException ex) ma tę drugą semantykę, będzie przechwytywać wszystko, co pochodzi od FormatException. - Greg Beech
@Alex No. "throw" bez "ex" przenosi oryginalny wyjątek, w tym oryginalny ślad stosu, w górę. Dodanie "ex" powoduje zresetowanie śledzenia stosu, więc naprawdę dostajesz inny wyjątek niż oryginał. Jestem pewien, że ktoś inny potrafi to lepiej wyjaśnić niż ja. :) - Samantha Branham
-1: Ten kod jest wyjątkowo kruchy - twórca biblioteki mógł się spodziewać jego zastąpienia throw new FormatException(); z throw new NewlyDerivedFromFormatException(); bez łamania kodu przy użyciu biblioteki, i będzie obowiązywać w przypadku wszystkich przypadków wyjątków, z wyjątkiem sytuacji, gdy ktoś użył == zamiast is (lub po prostu catch (FormatException)). - Sam Harwell