Fangen mehrere Ausnahmen auf einmal?
Es wird davon abgeraten, einfach fangen System.Exception
. Stattdessen werden nur die "bekannten" Ausnahmen sollen abgefangen werden.
Nun, das führt manchmal zu unnötig wiederholenden code, zum Beispiel:
try
{
WebId = new Guid(queryString["web"]);
}
catch (FormatException)
{
WebId = Guid.Empty;
}
catch (OverflowException)
{
WebId = Guid.Empty;
}
Frage ich mich: gibt es eine Möglichkeit, zu fangen beide Ausnahmen und nur nennen die WebId = Guid.Empty
wieder einmal telefonieren?
Dem gegebenen Beispiel ist relativ einfach, da es nur eine GUID
. Aber Stell dir mal code wo ändern Sie ein Objekt mehrere Male, und wenn einer von den Manipulationen nicht in einem erwarteten Art und Weise, die Sie möchten, auf "reset" die object
. Allerdings, wenn es ist eine unerwartete Ausnahme, ich will auch noch zu werfen, höher.
InformationsquelleAutor der Frage Michael Stum | 2008-09-25
Du musst angemeldet sein, um einen Kommentar abzugeben.
Fangen
System.Exception
an und schalten Sie den TypenInformationsquelleAutor der Antwort Joseph Daigle
EDIT: ich kann mich mit anderen, die sagen, dass, wie von C# 6.0, Ausnahme filtern sind jetzt völlig in Ordnung Weg zu gehen:
catch (Exception ex) when (ex is ... || ex is ... )
Außer, dass ich immer noch eine Art Hass den man-lang-line-layout und würde persönlich lag der code wie den folgenden. Ich denke, das ist so funktional wie ästhetisch, da ich glaube, es verbessert das Verständnis. Einige können nicht einverstanden:
ORIGINAL:
Ich weiß, ich bin ein wenig spät zur party hier, aber holy smoke...
Schneiden direkt auf den Punkt, diese Art von Duplikaten einer früheren Antwort, aber wenn Sie wirklich wollen, zu führen eine gemeinsame Aktion für mehrere exception-Typen und halten das ganze sauber und ordentlich im Rahmen der eine-Methode, warum man nicht einfach ein lambda/closure - /inline-Funktion zu tun, sowas wie das folgende? Ich meine, die Chancen stehen Recht gut, dass am Ende werden Sie erkennen, dass Sie nur wollen, dass die Schließung eine eigene Methode, die Sie nutzen können alle über dem Platz. Aber dann wird es super einfach zu tun, ohne tatsächlich verändert Sie den rest des Codes auch strukturell. Richtig?
Ich kann mir nicht helfen, aber Frage mich (Warnung: ein wenig Ironie/Sarkasmus vor), warum auf der Erde zu gehen, um alle diese Bemühungen, im Grunde ersetzen Sie einfach die folgende:
...mit ein paar verrückte Variante dieser code-smell, ich meine z.B. nur zu behaupten, dass Sie sparen ein paar Tastenanschläge.
Weil es ist sicher nicht automatisch besser lesbar.
Zugegeben, ich verließ die drei identische Instanzen von
/* write to a log, whatever... */return;
aus dem ersten Beispiel.Aber das ist sozusagen mein Punkt. Y ' all gehört haben von Funktionen/Methoden, richtig? Ernst. Schreiben Sie einen gemeinsamen
ErrorHandler
- Funktion, und rufen Sie es von jeder catch-block.Wenn Ihr mich fragt, ist das zweite Beispiel (mit dem
if
undis
keywords) ist sowohl deutlich weniger lesbar sind, und gleichzeitig deutlich mehr Fehler-anfällig während der maintenance phase Ihres Projekts.Die Erhaltungsphase, für alle, die vielleicht relativ neu in der Programmierung, umfassen 98.7% oder mehr der gesamten Lebensdauer des Projekts, und den Armen schmuck, die Wartung ist fast sicher gehen, um zu sein jemand anderen als Sie. Und es gibt eine sehr gute chance, Sie verbringen 50% Ihrer Zeit auf der Arbeit, fluchen Sie Ihren Namen.
Und natürlich FxCop bellt Sie und so haben Sie auch fügen Sie ein Attribut, um Ihren code, der hat genau die zip zu tun mit dem running-Programm, und ist nur da, um zu sagen, FxCop zu ignorieren, ein Problem, das in 99.9% der Fälle ist es völlig korrekt Kennzeichnen. Und, sorry, habe ich verwechselt werden könnten, aber nicht, dass die "ignorieren" - Attribut am Ende tatsächlich für Sie zusammengestellt, die Ihre app?
Würde putting die gesamte
if
test auf einer Linie, damit es besser lesbar? Ich denke nicht so. Ich meine, ich hatte noch einen anderen Programmierer vehement argumentieren einmal vor langer Zeit, dass man mehr code auf eine Zeile machen würde, es "schneller laufen." Aber natürlich, er war stark raving Nüsse. Versucht ihm zu erklären (mit einem geraden Gesicht-das war eine Herausforderung), wie der interpreter oder compiler brechen würde, die lange Linie auseinander in diskreten ein-instruction-per-line-Anweisungen--im wesentlichen identisch zu dem Ergebnis, wenn er ging voran und machte einfach den code lesbar, anstatt zu versuchen, sich-clever mit dem compiler-hatte keine Wirkung auf ihn zu löschen. Aber ich schweife ab.Wie viel weniger lesbar macht dieses erhalten, wenn Sie fügen Sie drei weitere exception-Typen, ein oder zwei Monate ab jetzt? (Antwort: es wird ein viel weniger lesbar).
Einer der wichtigsten Punkte, wirklich, ist, dass die meisten der Punkt der Formatierung der textuellen Quellcode, wir sind alle auf der Suche an jedem Tag zu machen, ist es wirklich wirklich offensichtlich zu anderen Menschen, was eigentlich passiert, wenn der code ausgeführt wird. Weil der compiler wandelt den Quellcode in etwas völlig anderes und konnte nicht weniger kümmern uns um Ihren code zu formatieren. Also alles-auf-eine-Linie Total Scheiße, auch.
Nur sagen...
InformationsquelleAutor der Antwort Craig
Wie andere haben darauf hingewiesen, können Sie einen
if
- Anweisung in deinem catch-block, um zu bestimmen, was Los ist. C#6 unterstützt das Exception-Filter, so werden die folgenden arbeiten:Den
MyFilter
Methode könnte dann so Aussehen:Alternativ kann dies alles geschehen eingebunden (auf der rechten Seite die wenn-Anweisung muss ein boolescher Ausdruck sein).
Dies ist anders als mit einem
if
- Anweisung in dercatch
block, mit Ausnahme von filtern nicht entspannen Sie den Stapel.Können Sie herunterladen Visual Studio 2015 check this out.
Wenn Sie möchten weiterhin mit Visual Studio 2013 können Sie installieren Sie die folgenden nuget-Paket:
Zum Zeitpunkt des Schreibens, dies schließt die Unterstützung für C# 6.
InformationsquelleAutor der Antwort Joe
Nicht in C# leider, als müssten Sie eine Ausnahme-filter zu tun, es und C# nicht aussetzen, dass die Funktion des MSIL. VB.NET nicht haben diese Fähigkeit, obwohl, z.B.
Was Sie tun könnten, ist die Verwendung einer anonymen Funktion Kapseln Ihrer auf-Fehler-code, und dann nennen Sie es in diese spezifische catch-Blöcke:
InformationsquelleAutor der Antwort Greg Beech
Der Vollständigkeit halber, da .NET 4.0 der code kann so geschrieben:
TryParse nie exceptions wirft und gibt false zurück, falls das format ist falsch, die Einstellung WebId zu
Guid.Empty
.Seit C# 7 können Sie verhindern, dass eine variable in einer separaten Zeile:
Können Sie auch erstellen von Methoden für die Analyse der Rückkehr Tupel, die nicht verfügbar sind .NET Framework noch als version 4.6:
Und verwenden Sie wie folgt:
Nächsten update nutzlos für diese nutzlose Antwort kommt, wenn Dekonstruktion der out-Parameter in C# implementiert 12. 🙂
InformationsquelleAutor der Antwort Athari
Wenn Sie können, aktualisieren Sie Ihre Anwendung auf C# 6 du hast Glück. Der neue C# - version implementiert hat, mit der Ausnahme der Filter. So können Sie schreiben:
Einige Leute denken, dass dieser code ist der gleiche wie
Aber auch nicht. Das ist eigentlich das einzige neue feature in C# 6 ist nicht möglich, Sie zu emulieren, die in vorherigen Versionen. Zunächst ein re-throw bedeutet mehr Aufwand als das überspringen der Fang. Zweitens, es ist nicht semantisch äquivalent. Das neue feature behält der Stapel intakt, wenn Sie Ihren code Debuggen. Ohne diese Funktion ist der crash-dump ist weniger nützlich oder gar nutzlos.
Sehen die Diskussion über diese auf CodePlex. Und ein Beispiel, welches den Unterschied.
InformationsquelleAutor der Antwort Maniero
Wenn Sie nicht möchten, verwenden Sie eine
if
- Anweisung innerhalb dercatch
Bereiche, inC# 6.0
können SieException Filters
syntax wurde bereits unterstützt von der CLR in den vorhergehenden Versionen, aber gab es nur inVB.NET
/MSIL
:Dieser code wird fangen die
Exception
nur, wenn es einInvalidDataException
oderArgumentNullException
.Tatsächlich, Sie können grundsätzlich jeden Zustand im inneren, dass
when
Klausel:Beachten Sie, dass im Gegensatz zu einer
if
Anweisung innerhalb dercatch
's scope,Exception Filters
wegwerfen kannExceptions
und wenn Sie es tun, oder wenn die Bedingung nichttrue
die nächstencatch
Bedingung wird ausgewertet statt:Wenn es mehr als eine
true
Exception Filter
- die ersten werden akzeptiert:Und wie Sie sehen können, in der
MSIL
wird der code nicht übersetztif
Aussagen, aber zuFilters
undExceptions
nicht werfen innerhalb der gekennzeichneten Bereiche sind mitFilter 1
undFilter 2
aber den filter werfen, dieException
fehl, stattdessen auch den letzten Vergleich Wert gedrückt, um den stack vor derendfilter
Befehl bestimmen den Erfolg/Misserfolg des filters (Catch 1
XORCatch 2
wird ausgeführt entsprechend):Auch, speziell
Guid
hat dieGuid.TryParse
Methode.InformationsquelleAutor der Antwort Tamir Vered
Akzeptierte Antwort scheint akzeptabel, außer, dass CodeAnalysis/FxCop wird sich über die Tatsache, dass es beim fangen einer Allgemeinen exception-Typ.
Es scheint auch den operator "is" könnte sich verschlechtern die Leistung etwas.
CA1800: nicht gegossen unnötig sagt, zu "prüfen, testen das Ergebnis der 'as' operator statt", aber wenn Sie das tun, werden Sie mehr code schreiben, als wenn Sie fangen jede Ausnahme einzeln.
Jedenfalls, hier ist was ich tun würde:
InformationsquelleAutor der Antwort Matt
Dies ist eine Variante des Matt ' s Antwort (ich fühle, dass diese ist ein wenig cleaner)...eine Methode verwenden:
Alle anderen Ausnahmen die geworfen werden und der code
WebId = Guid.Empty;
nicht getroffen werden. Wenn Sie nicht möchten, dass weitere Ausnahmen zum Absturz Ihres Programms, fügen Sie einfach diese, NACHDEM die beiden anderen Fänge:InformationsquelleAutor der Antwort bsara
@Micheal
Leicht überarbeitete version des Codes:
String-Vergleiche sind hässlich und langsam.
InformationsquelleAutor der Antwort FlySwat
in C# 6 der empfohlene Ansatz ist die Verwendung von Ausnahme-Filter, hier ein Beispiel:
InformationsquelleAutor der Antwort SHM
Joseph Daigle Antwort ist eine gute Lösung, aber ich fand die folgende Struktur ein wenig aufgeräumter und weniger fehleranfällig.
Gibt es ein paar Vorteile der Invertierung der Ausdruck:
Es kann auch komprimiert werden, um eine einzelne Linie (wenn auch nicht sehr hübsch)
Edit:
Die Ausnahme filtern in C# 6.0 wird die syntax ein bisschen sauberer und kommt mit einem Reihe anderer Vorteile über alle aktuellen Lösung. (vor allem das verlassen der stack unverletzt)
Hier ist, wie das gleiche problem Aussehen würde mit C# 6.0 syntax:
InformationsquelleAutor der Antwort Stefan T
Wie etwa
InformationsquelleAutor der Antwort Maurice
Mit C# 7 die Antwort von Michael Stum verbessert werden kann, während die Lesbarkeit einer switch-Anweisung:
InformationsquelleAutor der Antwort Fabian
Warnte und Warnte: Noch eine andere Art, funktionalen Stil.
Was ist in dem link beantwortet nicht deine Frage direkt, aber es ist trivial zu erweitern, dass es so Aussehen:
(Im Grunde ein weiteres leeres
Catch
überlastung, das sich immer wieder selbst)Die größere Frage ist warum. Ich glaube nicht, dass die Kosten höher als der Gewinn hier 🙂
InformationsquelleAutor der Antwort nawfal
InformationsquelleAutor der Antwort Konstantin Spirin
Update 2015-12-15: Siehe https://stackoverflow.com/a/22864936/1718702 für C#6. Es ist ein sauberer und nun standard in der Sprache.
Ausgerichtet für Menschen, die wollen ein elegantere Lösung zu fangen, einmal filtern und Ausnahmen, verwende ich eine extension-Methode, wie unten gezeigt.
Hatte ich bereits diese Erweiterung in meine Bibliothek, die ursprünglich für andere Zwecke, aber es funktionierte einfach perfekt für
type
Prüfung auf Ausnahmen. Plus, imho, es sieht sauberer aus, als ein Haufen von||
Aussagen. Auch, im Gegensatz zu den akzeptierten Antworten, ich bevorzuge explizite Ausnahmebehandlung soex is ...
hatte undesireable Verhalten als derrived Klassen zugeordnet werden, gibt es übergeordnete Typen).Nutzung
IsAnyOf.cs Extension (Siehe Vollständige Fehlerbehandlung Beispiel für Abhängigkeiten)
Vollständige Fehlerbehandlung Beispiel (Kopieren und Einfügen, um neue Console app)
Zwei Beispiel NUnit Unit-Tests
Passende Verhalten für
Exception
Typen genau ist (ie. Ein Kind IST NICHT ein Spiel für jede Ihrer übergeordneten Typen).InformationsquelleAutor der Antwort HodlDwon
Ausnahme-Filter sind jetzt in c# 6+. Sie können tun,
InformationsquelleAutor der Antwort Mat J
Da fühlte ich, wie diese Antworten berührte nur die Oberfläche, ich habe versucht, ein wenig tiefer zu Graben.
So, was wir wirklich tun möchten, ist etwas, das nicht kompiliert, sagen:
Der Grund, warum wir wollen, das ist, weil wir nicht wollen, dass der exception-handler catch-Dinge, die wir später brauchen in den Prozess. Sicher, wir können eine Exception auffangen und überprüfen Sie mit einem 'wenn' was zu tun, aber lassen Sie uns ehrlich sein, wir wollen nicht wirklich, dass. (FxCop, debugger, uglyness)
Warum also nicht diesen code, kompilieren Sie - und wie können wir es zu hacken, in einer solchen Weise, dass es wird?
Wenn wir Blick auf den code werfen, was wir wirklich tun möchten den Anruf weiterleiten. Jedoch, gemäß der MS-Partition II, IL exception-handler blockiert wird nicht funktionieren, wie das, was in diesem Fall Sinn macht, denn das würde bedeuten, dass die 'Ausnahme' - Objekt kann verschiedene Typen haben.
Oder schreiben Sie im code, bitten wir den compiler, so etwas zu tun (gut, es ist nicht ganz korrekt, aber es ist der nächste mögliche Sache, die ich denke):
Dem Grund, dass diese nicht kompiliert wird, ist ziemlich offensichtlich: was für ein Typ und Wert der$Ausnahme " - Objekt haben (die sind hier gespeichert in der Variablen 'e')? Die Art und Weise wollen wir den compiler zu handhaben, ist zu beachten, dass der gemeinsame Basistyp der beiden Ausnahmen ist die 'Ausnahme', verwenden, die für eine variable enthalten Ausnahmen, und dann mit nur zwei Ausnahmen, die gefangen sind. Die Art und Weise umgesetzt wird dies in IL ist als 'filter', die verfügbar ist in VB.Net.
Machen, damit es funktioniert in C#, brauchen wir eine temporäre variable mit dem richtigen 'Ausnahme' Basis-Typ. Um den Ablauf der Steuerung den code, wir können hinzufügen, einige Zweige. Hier geht:
Die offensichtlichen Nachteile sind, dass wir kann nicht erneut ausgelöst werden, richtig, und -lasst uns ehrlich sein -, dass es durchaus die hässliche Lösung. Die uglyness kann behoben werden, ein bisschen durch die Durchführung Zweig Beseitigung, wodurch die Lösung leicht besser:
Dass Blätter nur um die 're-throw'. Damit dies funktioniert, müssen wir in der Lage zu führen Sie die Behandlung innerhalb der 'catch' - block - und der einzige Weg, um diese Arbeit zu machen, ist durch einen Fang 'Ausnahme' - Objekt.
Wir an dieser Stelle kann eine separate Funktion behandelt, die verschiedenen Arten von Ausnahmen durch überlast Auflösung, oder die Ausnahme behandeln. Beide haben Nachteile. Um zu starten, hier ist der Weg, es zu tun mit einer helper-Funktion:
Und die andere Lösung ist, fangen die Exception-Objekt und behandelt es entsprechend. Die wörtliche übersetzung für diese, basierend auf dem Kontext oben ist dieser:
Also zu dem Schluss:
InformationsquelleAutor der Antwort atlaste
So dass Sie wiederholen viel code innerhalb jeder Ausnahme-Schalter? Klingt wie das extrahieren einer Methode wäre es Gottes Idee, nicht wahr?
Also dein code kommt unten zu diesem:
Ich Frage mich, warum niemand bemerkt, dass code-Duplikation.
Von C#6 Sie haben außerdem die Ausnahme-Filter wie schon von anderen erwähnt. So können Sie ändern Sie den code oben auf dieser:
InformationsquelleAutor der Antwort HimBromBeere
Dies ist ein klassisches problem, das jeden C# - Entwickler Gesichter schließlich.
Lassen Sie mich brechen Sie Ihre Frage in 2 Fragen. Das erste,
Kann ich mehrere Ausnahmen abfangen auf einmal?
In kurzen, Nein.
Führt zu der nächsten Frage,
Wie kann ich das vermeiden doppelten code zu schreiben gegeben, dass ich nicht abfangen kann mehrere Ausnahme-Typen in der gleichen catch () - block?
Angesichts Ihrer bestimmten Probe, wo die fall-back-Wert ist, Billig zu bauen, wie ich gehen Sie folgendermaßen vor:
Also der code sieht folgendermaßen aus:
Wenn eine Ausnahme ausgelöst wird, dann WebId ist nie festgelegt auf die Hälfte des rechnerisch ermittelten Wertes, und bleibt Guid.Leer.
Wenn Bau die fall-back-Wert ist teuer, und der Reset-Wert ist viel billiger, dann würde ich verschieben Sie den reset-code in eine eigene Funktion:
InformationsquelleAutor der Antwort Jeffrey Rennie
Hinweis, dass ich einen Weg finden, es zu tun, aber das sieht eher wie material für The Daily WTF:
InformationsquelleAutor der Antwort
Wollte noch meine kurze Antwort zu diesem thread schon lange. Etwas was noch nicht erwähnt wurde ist die Reihenfolge der catch-Anweisungen, genauer gesagt, Sie müssen sich bewusst sein, der Umfang jeder Art von Ausnahme, die Sie versuchen zu fangen.
Zum Beispiel, wenn Sie eine "catch-all" - Ausnahme, wie Ausnahme es wird preceed alle anderen catch-Anweisungen und Sie werden natürlich bekommen compiler-Fehler allerdings, wenn Sie die Bestellung stornieren können Sie die Kette Ihrer catch-Anweisungen (bit-ein anti-pattern, denke ich) kann man den catch-all Ausnahme Typ am Boden und diese werden alle Ausnahmen erfassen, nicht gerecht für die, die höher in try..catch-block:
Empfehle ich Leuten überprüfen Sie in diesem MSDN-Dokument:
Ausnahme-Hierarchie
InformationsquelleAutor der Antwort Tahir Khalid
Vielleicht versuchen, halten Sie Ihren code einfach wie putting den gemeinsamen code in einer Methode, die, wie in jedem anderen Teil des Codes, die nicht innerhalb eines catch-Klausel?
E. g.:
Nur wie ich es tun würde, versuchen zu finden, die einfach schön ist Muster
InformationsquelleAutor der Antwort Żubrówka
Rufen Sie einfach den try-und catch-doppelt.
So Einfach ist das!!
InformationsquelleAutor der Antwort scholar guy
In c# 6.0,Ausnahme Filtern Verbesserungen für die Ausnahmebehandlung
InformationsquelleAutor der Antwort Kashif