Catch Exception mit Bedingung
Hinweis: ich bin sehr glücklich, Ihnen zu sagen, dass Ausnahme-Filter sind nun in der C# - 6.0-Sprache.
Dies ist ein Gedankenexperiment, ich bin an deiner Meinung interessiert: Macht es Sinn für Sie? Wissen Sie, ob etwas ähnliches bereits vorgeschlagen worden, für die Programmiersprache C#? Ich würde nicht einmal wissen, wo Sie zu senden, so ein Vorschlag...
Die Idee ist Einführung syntax-Elementen zum abfangen einer Ausnahme nur dann, wenn es erfüllt eine bestimmte Bedingung.
Einer use-case-Beispiel ist beim arbeiten mit COM-Interop: Alles wirft immer ein COMException
. Die eigentliche Unterscheidung-Fehler-code ist enthalten in seiner Botschaft.
So was (Vorschlag 1):
try
{
...
}
catch (COMException ex where ex.Message.Contains("0x800706BA"))
{
//RPC server unavailable
}
catch (COMException ex where ex.Message.Contains("0x80010001"))
{
//Call rejected by callee
}
übersetzt:
try
{
...
}
catch (COMException ex)
{
if (ex.Message.Contains("0x800706BA"))
{
//RPC server unavailable
}
else if (ex.Message.Contains("0x80010001"))
{
//Call rejected by callee
}
else
{
throw;
}
}
Ähnliche Fälle sind: SoapException
, XmlException
...
Anderes Szenario ist, wenn Ausnahmen gewickelt sind als innere Ausnahmen innerhalb einer Allgemeinen Ausnahme, und die fangen Logik, sollte davon abhängen, die innere Ausnahme.
Sagen, wir haben eine API, die wraps Ausnahmen wie diese: catch (NumberFormatException ex) { throw new BusinessException(ex) }
.
Was (Vorschlag 2A):
try
{
...
}
catch (inner NumberFormatException nfex)
{
...
}
übersetzt:
catch (Exception ex where ex.InnerException is NumberFormatException)
{
NumberFormatException nfex = ex.InnerException;
...
}
oder (2B):
catch (BusinessException bex inner NumberFormatException nfex)
{
...
}
übersetzt:
catch (BusinessException bex where bex.InnerException is NumberFormatException)
{
NumberFormatException nfex = bex.InnerException;
...
}
In in diesem Fall (ursprünglich aus Java) könnte es Aussehen (2C):
catch (RemoteAccessException raex inner inner MyException mex)
{
...
}
- Die bar ist hoch für neue Sprachfeatures in C#. Und dieses feature fügt nichts, was Sie nicht bereits tun einfach meiner Meinung nach.
- Nein, es ist nur syntaktischer Zucker. Aber irgendwie extrapoliert die Ideen, die hinter LINQ (zumindest Vorschlag 1).
- Ich denke, man kann es auf Microsoft Connect, wo in können Sie diese Anfrage als feature.
- Es ist nicht syntaktischer Zucker. Das Verhalten ist anders. Siehe (blogs.msdn.com/b/clrteam/archive/2009/08/25/...) für eine detaillierte Erklärung, wie zwei pass-exception handling arbeitet in der CLR.
- Das ist ein interessanter Punkt. Auf der anderen Seite, keine der .NET-Spezifikation garantiert keine bestimmte Reihenfolge, in der finally-Blöcke werden ausgeführt? Bisher dachte ich Nein, so ein Programmierer sollte verlassen Sie sich nie auf eine bestimmte Reihenfolge sowieso. Setzen Sie es auf diese Weise, wird das angegebene Verhalten ist gleich, es gibt nur einige unspezifische Unterschiede unter...
- Verwandelte sich in ein community-wiki, denke das ist besser geeignet.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Entsprechend der try-catch-C# - Referenz für Visual Studio 2015 RC dies ist nun umgesetzt:
VB.Net diese Funktion hat der Ausnahme-filter wie unten gezeigt
So unterstützt wird dies durch die CLR-aber das feature wird nicht verfügbar gemacht, in C#
Angeblich F# ist diese Funktion auch, aber ich weiß nicht viel über F# zu zeigen, Beispiel.
Ausnahmen und Arten sind eng verwandt. Wenn Sie möchten, zu unterscheiden zwischen zwei verschiedenen Arten von Ausnahmen, sollten Sie die beiden Ausnahme-Typen. In Ihrem Beispiel, Sie hätte ein Com800706BAException und ein Com80010001Exception.
Nun, dies ist nicht immer möglich oder machbar, zum Beispiel, wenn das zugrunde liegende system verwendet Fehler-codes anstelle von exceptions. In diesem Fall ist deine Methode kann hilfreich sein. Aber diese Sprache-Funktion leicht missbraucht werden. Zum Beispiel, könnten Sie tun, Fehlerbehandlung, die ist nicht Typ-sicher:
Wenn Sie prüfen wollen, die innere Ausnahme von einer Ausnahme, du machst den Fehler Behandlung auf der falschen Ebene. Die Idee ist, dass eine Methode wirft eine generalisierte Ausnahme abstract der Anrufer aus dem inneren funktionieren der Methode. Wenn Sie hängen auf einige Ausnahme-Sie sind eng gekoppelt an die Umsetzung der Methode. Das ist schlecht.
Entweder eine separate, generalisierte Ausnahme geworfen werden sollte, oder die Fehlerbehandlung sollte verschoben werden, innerhalb der Methode.
COMException
. Ich bin der Kunde der Interop, nicht der Programmierer...Warum Backen etwas in der Sprache, die ist einfach zu tun, eh?
Vorschlag 1 ist leicht behandelt mit einem gezieltem switch-Anweisung innerhalb des catch - auf diese Weise können Sie befassen sich mit der COM-Ausnahmen, die Sie wollen, und nur rethrow alles, was Sie nicht wollen, zu beschäftigen.
Das problem mit Vorschlag 2 ist, dass der Ausnahme-Stapel können beliebig tief, und könnte (oder wird) enthalten:
mehrere verschachtelte Instanzen der gleichen Art von Ausnahme - was sollte man Ihrer Suchanfrage-syntax beschäftigen?
unterschiedliche Ausnahmen, die sich aus den gleichen Basis-exception* - wenn Ihre Anfrage-syntax legt fest, dass die untere Ebene base Ausnahmen dann, dass könnte passen eine ganze Reihe von höheren Ebene Ausnahmen in den Stapel, die man(N) Sie sind auf der Suche zu verarbeiten?
Meisten der Zeit, wenn Sie Durchlaufen die Ausnahme-Stapel, die Sie nicht interessieren, abrufen der Ausnahme, dass auf halbem Weg nach unten den Stapel, anstatt Sie zu Fuss die Ausnahme-Stapel und Holen Sie der erste, der Protokollierung. Den rest der Zeit, Sie kümmert sich nur um die Letzte (äußere) Ausnahme. Ich persönlich kann nicht eine Zeit erinnern, wo hatte ich das Bedürfnis zu programmgesteuert abfangen/behandeln einer Ausnahme, die wurde begraben irgendwo in der Mitte des Stapels, es war schon immer ersten, letzten oder alle von Ihnen.
*abgesehen von der Tatsache, dass alle Ausnahmen, die der Ableitung von System.Ausnahme - ich war also mehr entlang der Linien von MyBaseException, die alle Ihre eigene Ausnahmen ableiten.
Denke ich, ziemlich schwierig und verwirrend:
Was, wenn Sie Ihre Ausnahme-Bedingung löst eine Ausnahme aus, wie gut? Wo und wie soll das neue Ausnahme behandelt werden?
Ich bin mir nicht sicher, ich mag es, dass viel. First off, es Klang wie eine wirklich nette Idee, aber dann kam ich zu denken, dass wenn die Beurteilung syntaktischer Zucker für diese Art der Sache, die Leute werden wahrscheinlich Missbrauch Ausnahmen, wenn sich ein status-code angebracht.
Als ein paar Leute haben bereits darauf hingewiesen, dieser ist bereits in VB, jedoch könnte man leicht etwas tun, ähnlich wie in C#:
So, es ist wirklich nur syntaktischer Zucker.
Ist die Sache mit Ausnahmen ist, dass (wie oft diskutiert auf dieser Seite), Sie verletzen die sequenzielle Struktur des Programms, möglicherweise überspringen eine Menge von code und Tauchen den Stapel, wenn Sie wirklich nicht wollen, dass. Dies ist der Grund, warum ich don ' T denke, Sie sind gut für nichts, aber sehr außergewöhnlichen Bedingungen, und wenn Sie wirklich kann irgendwie behandeln diese Bedingungen, es sollte etwas von einem Schmerz (try{}catch{if(..)} usw.), so, dass die Menschen nicht geneigt, Ausnahmen für mehr als diese außergewöhnlichen Bedingungen.
Da c# 7.0 diese Art von Sachen, die bereits unterstützt. Hier ist die vollständige Referenz.
Hier ist ein code-snippet.