EDIT: Ich stimme mit anderen, die sagen, dass ab C# 6.0, Ausnahme-Filter sind jetzt eine völlig gute Möglichkeit zu gehen: catch (Exception ex) when (ex is ... || ex is ... )
Allerdings hasse ich immer noch das einzeilige Layout und würde persönlich den Code wie folgt gestalten. Ich denke, dass dies sowohl funktional als auch ästhetisch ist, da ich glaube, dass es die Verständlichkeit verbessert. Manche mögen anderer Meinung sein:
catch (Exception ex) when (
ex is ...
|| ex is ...
|| ex is ...
)
ORIGINAL:
Ich weiß, ich bin ein wenig zu spät zur Party hier, aber heiliger Bimbam...
Um es gleich auf den Punkt zu bringen, dies ist eine Art Duplikat einer früheren Antwort, aber wenn Sie wirklich eine gemeinsame Aktion für mehrere Ausnahmetypen durchführen möchten und die ganze Sache sauber und ordentlich innerhalb des Anwendungsbereichs der einen Methode halten, warum nicht einfach eine Lambda/Schließung/Inline-Funktion verwenden, um etwas wie das Folgende zu tun? Ich meine, die Chancen stehen gut, dass Sie am Ende feststellen, dass Sie diese Schließung zu einer separaten Methode machen wollen, die Sie überall verwenden können. Aber dann wird es super einfach sein, das zu tun, ohne den Rest des Codes strukturell zu verändern. Oder?
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 ); }
}
Ich kann nicht umhin, mich zu fragen ( Warnung: ein wenig Ironie/Sarkasmus voraus), warum um alles in der Welt sollte man sich diese Mühe machen, um im Grunde nur Folgendes zu ersetzen:
try
{
// try some stuff
}
catch( FormatException ex ){}
catch( OverflowException ex ){}
catch( ArgumentNullException ex ){}
...mit einer verrückten Variante dieses nächsten Codegeruchs, ich meine Beispiel, nur um so zu tun, als würden Sie ein paar Tastenanschläge sparen.
// 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;
}
Denn sie ist nicht automatisch besser lesbar.
Zugegeben, ich habe die drei identischen Instanzen von /* write to a log, whatever... */ return;
aus dem ersten Beispiel.
Aber darum geht es mir ja auch. Ihr habt doch alle schon von Funktionen/Methoden gehört, oder? Ganz im Ernst. Schreiben Sie eine gemeinsame ErrorHandler
Funktion und rufen sie z.B. von jedem Catch-Block aus auf.
Wenn Sie mich fragen, ist das zweite Beispiel (mit der if
et is
Schlüsselwörter) ist sowohl deutlich weniger lesbar als auch gleichzeitig deutlich fehleranfälliger in der Wartungsphase Ihres Projekts.
Die Wartungsphase wird für jeden, der relativ neu in der Programmierung ist, 98,7 % oder mehr der gesamten Lebensdauer Ihres Projekts ausmachen, und der arme Trottel, der die Wartung durchführt, wird mit ziemlicher Sicherheit jemand anderes als Sie sein. Und es besteht eine sehr gute Chance, dass er 50% seiner Zeit damit verbringt, Ihren Namen zu verfluchen.
Und natürlich bellt FxCop Sie an und Sie müssen également fügen Sie Ihrem Code ein Attribut hinzu, das mit dem laufenden Programm nichts zu tun hat und nur dazu dient, FxCop mitzuteilen, dass es ein Problem ignorieren soll, das es in 99,9 % der Fälle völlig korrekt anzeigt. Und, entschuldigen Sie, vielleicht irre ich mich, aber wird dieses "Ignorieren"-Attribut nicht am Ende tatsächlich in Ihre Anwendung kompiliert?
Wäre es sinnvoll, die gesamte if
Test in einer Zeile die Lesbarkeit verbessern? Nein, das glaube ich nicht. Ich meine, ein anderer Programmierer hat vor langer Zeit einmal vehement behauptet, dass mehr Code in einer Zeile dazu führt, dass er "schneller läuft". Aber natürlich war er völlig verrückt. Der Versuch, ihm zu erklären, wie der Interpreter oder Compiler diese lange Zeile in einzelne Anweisungen pro Zeile zerlegen würde - im Wesentlichen identisch mit dem Ergebnis, wenn er den Code einfach lesbar gemacht hätte, anstatt zu versuchen, den Compiler zu überlisten - hatte keinerlei Wirkung auf ihn. Aber ich schweife ab.
Wie viel weniger lesbar wird, wenn Sie in ein oder zwei Monaten drei weitere Ausnahmetypen hinzufügen? (Antwort: Es wird ein Los weniger lesbar).
Einer der wichtigsten Punkte ist, dass die Formatierung des textuellen Quellcodes, den wir alle jeden Tag sehen, vor allem dazu dient, anderen Menschen klar zu machen, was tatsächlich passiert, wenn der Code ausgeführt wird. Denn der Compiler verwandelt den Quellcode in etwas völlig anderes und kümmert sich nicht im Geringsten um die Formatierung Ihres Codes. Also ist "Alles-online" auch total scheiße.
Ich sage ja nur...
// super sucks...
catch( Exception ex )
{
if ( ex is FormatException || ex is OverflowException || ex is ArgumentNullException )
{
// write to a log, whatever...
return;
}
throw;
}
8 Stimmen
Wenn Sie .net 4 und höher verwenden, bevorzuge ich die Verwendung von Aggregateexception msdn.microsoft.com/de-us/library/system.aggregateexception.aspx
2 Stimmen
Bepenfriends- Seit System.Guid wirft nicht AggregateException Es wäre toll, wenn Sie (oder jemand) eine Antwort posten könnte, die zeigt, wie Sie es in eine AggregateException usw. einpacken würden.
1 Stimmen
Zur Verwendung
AggregateException
: Auslösen einer AggregateException in meinem eigenen Code28 Stimmen
"Es wird davon abgeraten, einfach System.Exception abzufangen." -und wenn die Methode 32 Arten von Ausnahmen auslösen kann, was tut man dann? für jede von ihnen separat fangen schreiben?
1 Stimmen
Behalten Sie es so bei, wie Sie es haben. Verschieben Sie den Code zu einem Fehler-Handler, wenn Sie so theres nur eine Zeile pro catch-Anweisung wünschen.
13 Stimmen
Wenn eine Methode 32 verschiedene Arten von Ausnahmen auslöst, ist sie schlecht geschrieben. Es ist entweder nicht fangen Ausnahmen es ist eigene Anrufe machen, es ist tun, viel zu viel in einer Methode, oder die Mehrheit / alle diese 32 sollte eine einzige Ausnahme mit einem Grund-Code sein.
2 Stimmen
Die akzeptierte Antwort ist nicht mehr aktuell; sehen Sie sich stattdessen diese an, da sie mit einer Bearbeitungsklausel am Anfang aktualisiert worden ist: stackoverflow.com/a/19329123/398630
0 Stimmen
Da dies in keiner der Antworten, die ich überflogen habe, erwähnt wurde, möchte ich nur sagen, dass Ihre anfängliche Aussage falsch ist. "Es ist nicht ratsam, einfach zu fangen
System.Exception
", ist nicht korrekt, es gibt sehr triftige Gründe, dies zu tun, es wird davon abgeraten nur fangenSystem.Exception
1 Stimmen
@giorgi, ich bin mir nicht sicher, ob das ein guter Leitfaden ist. Der Code sollte 32 Probleme nicht getrennt lösen, wenn die Lösung dieselbe ist. Wenn Sie dasselbe für xxxException und yyyException und Exception tun, fangen Sie einfach Exception (Elternteil der anderen beiden).
0 Stimmen
@Flynn1179, nicht unbedingt. Wenn Sie einen try..catch-Block auf der obersten Ebene Ihrer Anwendung haben, werden Sie die Fehler für mehrere Schichten erfassen. Sie fangen also potenziell IO-, DB-, http-, Comm-, Argument- und Domain-Ausnahmen ab.
0 Stimmen
@zameb, ich bezog mich auf Giorgis Beispiel einer einzelnen Methode, die zu viele Ausnahmen auslöst. Wie diese abgefangen werden, ist für meinen Punkt nicht relevant.