2013-12-16 9 views
8

Dies ist die eigentliche Quelle für .NET System.Exception.ToString:Warum ruft System.Exception.ToString virtuellen ToString nicht für innere Ausnahmen auf?

public override string ToString() 
{ 
    return this.ToString(true, true); 
} 

private string ToString(bool needFileLineInfo, bool needMessage) 
{ 
    string str1 = needMessage ? this.Message : (string) null; 
    string str2 = str1 == null || str1.Length <= 0 ? this.GetClassName() : this.GetClassName() + ": " + str1; 
    if (this._innerException != null) 
    str2 = str2 + " ---> " + this._innerException.ToString(needFileLineInfo, needMessage) + Environment.NewLine + " " + Environment.GetRuntimeResourceString("Exception_EndOfInnerExceptionStack"); 
    string stackTrace = this.GetStackTrace(needFileLineInfo); 
    if (stackTrace != null) 
    str2 = str2 + Environment.NewLine + stackTrace; 
    return str2; 
} 

Neben der schieren Hässlichkeit, kann man die feststellen, für alle inneren Ausnahmen das private, nicht-virtuelle ToString aufgerufen wird. Mit anderen Worten, wenn Sie ToString in Ihrer Ausnahme überlasten, wird es nicht aufgerufen, wenn Ihre Ausnahme verschachtelt ist. Oh, festhalten, stellt sich heraus, eingebaute Ausnahmen haben die gleichen Probleme, z.B. System.IO.FileNotFoundException druckt Pfad der Datei - es ist nicht ein Teil der Nachricht ist:

public override string ToString() 
{ 
    string str = this.GetType().FullName + ": " + this.Message; 
    if (this._fileName != null && this._fileName.Length != 0) 
    str = str + Environment.NewLine + Environment.GetResourceString("IO.FileName_Name", new object[1] 
    { 
     (object) this._fileName 
    }); 
    ... 
} 

Aber wenn Sie eine Instanz wickeln ... diese Informationen gehen verloren, wenn Sie die Ausnahmen Baum selbst und erkennen Ausnahmen durchqueren Geben Sie ToString ein oder rufen Sie sich selbst an und führen Sie ein banales Parsing durch.

Das ist eine lästige Unannehmlichkeit, die dazu führt, dass Protokoll-/Schreibfehler-Dialoge entweder Informationen verlieren oder fehleranfällig sind. Interessanterweise Mono gets it right.

Gibt es irgendeine versteckte Weisheit in der .NET-Version?

EDIT: Dies ist keine Meinung basierte Frage. Während ich diese Designauswahl als ärgerlich empfinde, würde ich gerne die Vorteile dieses Ansatzes kennenlernen. Sie zu kennen, kann bei der Entwicklung neuer Lösungen von Vorteil sein.

Antwort

1

Meiner Erfahrung nach ist die richtige Entscheidung der Framework-Designer nicht die Angabe der inneren Ausnahmedetails im Aufruf von ToString.

Oft wird das Ergebnis von ToString dem Endbenutzer präsentiert, falls die ausführende Anwendung dem Benutzer keine präziseren Informationen über die Art des Problems und mögliche Lösungen liefern kann.

In diesem Fall kann das Verschachteln interner Ausnahmedetails nicht nur für den Endbenutzer verwirrend sein, sondern auch ein potenzielles Sicherheitsrisiko darstellen. Das oben aufgeführte Beispiel für das Dateinamensproblem ist gut: Ich möchte die Verzeichnisinformationen einer Datei auf meinem Webserver keinem externen Benutzer zugänglich machen, falls die Datei nicht gefunden werden könnte (theoretisch würde die Ausnahme immer bestehen) richtig behandelt werden, um diese Exposition zu verhindern, aber keine Anwendung ist perfekt).

Wo die inneren Ausnahmedetails nützlich werden, wird der Anwendungsfehler irgendwo protokolliert (Ereignisprotokoll, Datei, Datenbank usw.). In diesem Fall werden Sie höchstwahrscheinlich mehr als nur die ToString-Details benötigen. Die Implikation ist also, dass Sie für diese Situationen sowieso Logging-Code haben müssen, der für das Extrahieren der entsprechenden Informationen verantwortlich ist.

Ich glaube, dass Microsoft dies früh erkannt hat, da einer der ersten Anwendungsblöcke, die sie ihrer Enterprise Library hinzufügten, die Exception Handling block war, die eine eingehende Traversierung und Aufzeichnung aller Ausnahmedetails einschließlich öffentlicher Eigenschaften für die Ausnahmen bietet sich.

+0

Ich verstehe Ihren Punkt, aber beachten Sie, dass die Präsentation von Ausnahme-Stack und/oder Call-Stack für den Benutzer ein Sicherheits-Rick sein kann. Ganz zu schweigen davon, dass der Standard 'ToString' auch die Eigenschaft 'Message' ausgibt, die sensible Daten enthalten kann. Wenn es sich also um eine bewusste Microsoft-Designentscheidung handelte, war es ein Mittelgrund, der weder der Sicherheit noch der Informativität diente. Für "Retail" -Programme sollte man das Ergebnis von 'ToString' gar nicht zeigen, für Inhouse-Tech braucht man mehr Informationen (es ist da draußen!). – gwiazdorrr

2

Exception.ToString() ist nichts, was den Benutzern präsentiert werden sollte. Es ist ist etwas, das den Entwicklern vielleicht in einer Protokolldatei präsentiert werden sollte.

Die Standardimplementierung von ToString() macht normalerweise das "Richtige".Beachten Sie, wie es verschachtelte Ausnahmen und mehrere Ausnahmen (wie AggregateException oder SqlException) und sogar Ausnahmen über eine Remoting-Grenze behandelt. Versuchen Sie, einen Fehler während der Deserialisierung von XML mit dem XML-Serializer zu erhalten, und Sie werden wirklich schätzen, wie viele Informationen Sie erhalten - normalerweise genug, um direkt auf die Ursache der Ausnahme zu verweisen.

Wenn etwas Bestimmtes angezeigt werden soll, sollten Sie Microsoft für dieses Problem kontaktieren. Insbesondere werden Sie sie wahrscheinlich nicht dazu bringen, Ihren überschriebenen ToString einfach aufzurufen. Klar, das will ich nicht. Wenn es jedoch etwas gibt, das Ihr ToString anzeigen wollte, dass das nicht der Fall ist, dann sprechen Sie mit ihnen und sehen Sie, ob es noch einen anderen Weg gibt, oder ob es etwas gibt, was sie in einem zukünftigen Release tun können.

Verwandte Themen