Wenn C # eine Ausnahme auslöst, kann es eine innere Ausnahme geben. Was ich tun möchte, ist die innerste Ausnahme zu erhalten, oder mit anderen Worten, die Blattausnahme, die keine innere Ausnahme hat. Ich kann dies in einer while-Schleife tun:
while (e.InnerException != null)
{
e = e.InnerException;
}
Aber ich fragte mich, ob es einen Einzeiler gab, mit dem ich dies stattdessen tun könnte.
c#
.net
exception
exception-handling
while-loop
Daniel T.
quelle
quelle
LibraryException -> LibraryException -> LibraryException -> MyException
. Meine Ausnahme ist immer die letzte in der Kette und hat keine eigene innere Ausnahme.LINQ
, fast alles zu tun, dass es komisch erscheint, wenn ich eine Schleife schreiben muss. Ich arbeite hauptsächlich mit Datenzugriff, also arbeite ich so ziemlich mitICollections
fast allem, was ich tue.LINQ
maskiert nicht nur die Tatsache, dass der Code im Wesentlichen noch eine Schleife haben muss? Gibt es in .NET echte satzbasierte Befehle?Antworten:
Einzeiler :)
while (e.InnerException != null) e = e.InnerException;
Einfacher geht es natürlich nicht.
Wie in dieser Antwort von Glenn McElhoe gesagt, ist dies der einzig zuverlässige Weg.
quelle
Exception.GetBaseException()
bei mir nicht.Ich glaube
Exception.GetBaseException()
, das Gleiche wie diese Lösungen.Vorsichtsmaßnahme: Aus verschiedenen Kommentaren haben wir herausgefunden, dass es nicht immer buchstäblich dasselbe tut, und in einigen Fällen bringt Sie die rekursive / iterierende Lösung weiter. Dies ist normalerweise die innerste Ausnahme, die dank bestimmter Arten von Ausnahmen, die die Standardeinstellung überschreiben, enttäuschend inkonsistent ist. Wenn Sie jedoch bestimmte Arten von Ausnahmen abfangen und einigermaßen sicherstellen, dass es sich nicht um seltsame Kugeln handelt (wie AggregateException), würde ich erwarten, dass die legitime innerste / früheste Ausnahme vorliegt.
quelle
GetBaseException()
die erste Root-Ausnahme nicht zurückgegeben.GetBaseException()
hat bei mir nicht funktioniert, da die oberste Ausnahme eine AggregateException ist.Das Durchlaufen von InnerExceptions ist der einzig zuverlässige Weg.
Wenn die abgefangene Ausnahme eine AggregateException ist, wird
GetBaseException()
nur die innerste AggregateException zurückgegeben.http://msdn.microsoft.com/en-us/library/system.aggregateexception.getbaseexception.aspx
quelle
Wenn Sie nicht wissen, wie tief die inneren Ausnahmen verschachtelt sind, führt kein Weg an einer Schleife oder Rekursion vorbei.
Natürlich können Sie eine Erweiterungsmethode definieren, die dies abstrahiert:
public static class ExceptionExtensions { public static Exception GetInnermostException(this Exception e) { if (e == null) { throw new ArgumentNullException("e"); } while (e.InnerException != null) { e = e.InnerException; } return e; } }
quelle
Ich weiß, dass dies ein alter Beitrag ist, aber ich bin überrascht, dass niemand vorgeschlagen hat,
GetBaseException()
welche Methode für dieException
Klasse gilt:catch (Exception x) { var baseException = x.GetBaseException(); }
Dies gibt es seit .NET 1.1. Dokumentation hier: http://msdn.microsoft.com/en-us/library/system.exception.getbaseexception(v=vs.71).aspx
quelle
Manchmal haben Sie viele innere Ausnahmen (viele sprudelnde Ausnahmen). In diesem Fall möchten Sie möglicherweise Folgendes tun:
List<Exception> es = new List<Exception>(); while(e.InnerException != null) { es.add(e.InnerException); e = e.InnerException }
quelle
Nicht ganz eine Zeile, aber nah:
Func<Exception, Exception> last = null; last = e => e.InnerException == null ? e : last(e.InnerException);
quelle
In der Tat ist so einfach, dass Sie verwenden könnten
Exception.GetBaseException()
Try //Your code Catch ex As Exception MessageBox.Show(ex.GetBaseException().Message, My.Settings.MsgBoxTitle, MessageBoxButtons.OK, MessageBoxIcon.Error); End Try
quelle
Sie müssen eine Schleife erstellen, und es ist sauberer, die Schleife in eine separate Funktion zu verschieben.
Ich habe eine Erweiterungsmethode erstellt, um damit umzugehen. Es gibt eine Liste aller inneren Ausnahmen des angegebenen Typs zurück und verfolgt Exception.InnerException und AggregateException.InnerExceptions.
In meinem speziellen Problem war das Verfolgen der inneren Ausnahmen komplizierter als gewöhnlich, da die Ausnahmen von den Konstruktoren von Klassen ausgelöst wurden, die durch Reflexion aufgerufen wurden. Die Ausnahme, die wir abfingen, hatte eine InnerException vom Typ TargetInvocationException, und die Ausnahmen, die wir tatsächlich betrachten mussten, waren tief im Baum vergraben.
public static class ExceptionExtensions { public static IEnumerable<T> innerExceptions<T>(this Exception ex) where T : Exception { var rVal = new List<T>(); Action<Exception> lambda = null; lambda = (x) => { var xt = x as T; if (xt != null) rVal.Add(xt); if (x.InnerException != null) lambda(x.InnerException); var ax = x as AggregateException; if (ax != null) { foreach (var aix in ax.InnerExceptions) lambda(aix); } }; lambda(ex); return rVal; } }
Die Verwendung ist ziemlich einfach. Wenn Sie zum Beispiel wissen möchten, ob wir auf a gestoßen sind
catch (Exception ex) { var myExes = ex.innerExceptions<MyException>(); if (myExes.Any(x => x.Message.StartsWith("Encountered my specific error"))) { // ... } }
quelle
Exception.GetBaseException()
?Sie können die Rekursion verwenden, um irgendwo eine Methode in einer Dienstprogrammklasse zu erstellen.
public Exception GetFirstException(Exception ex) { if(ex.InnerException == null) { return ex; } // end case else { return GetFirstException(ex.InnerException); } // recurse }
Verwenden:
try { // some code here } catch (Exception ex) { Exception baseException = GetFirstException(ex); }
Die vorgeschlagene Erweiterungsmethode (gute Idee @dtb)
public static Exception GetFirstException(this Exception ex) { if(ex.InnerException == null) { return ex; } // end case else { return GetFirstException(ex.InnerException); } // recurse }
Verwenden:
try { // some code here } catch (Exception ex) { Exception baseException = ex.GetFirstException(); }
quelle
public static Exception GetOriginalException(this Exception ex) { if (ex.InnerException == null) return ex; return ex.InnerException.GetOriginalException(); }
AggregateException.InnerExceptions
?Sie können dies auch tun, indem Sie
GetBaseException()
zweimal anrufen :Dies funktioniert, weil Sie, wenn es sich um eine handelt
AggregateException
, beim ersten Anruf zum innersten Nicht-AggregateException
Anruf gelangen und beim zweiten Anruf zur innersten Ausnahme dieser Ausnahme gelangen. Wenn die erste Ausnahme keine istAggregateException
, gibt der zweite Aufruf nur dieselbe Ausnahme zurück.quelle
Ich bin darauf gestoßen und wollte in der Lage sein, alle Ausnahmemeldungen aus dem Ausnahmestapel aufzulisten. Also habe ich mir das ausgedacht.
public static string GetExceptionMessages(Exception ex) { if (ex.InnerException is null) return ex.Message; else return $"{ex.Message}\n{GetExceptionMessages(ex.InnerException)}"; }
quelle