Beim Parsen von Benutzereingaben wird generell empfohlen , keine Ausnahmen auszulösen und abzufangen, sondern Validierungsmethoden zu verwenden. In der .NET-BCL ist dies beispielsweise der Unterschied zwischen int.Parse
(löst eine Ausnahme für ungültige Daten aus) und int.TryParse
(Rückgabe false
für ungültige Daten).
Ich entwerfe meine eigenen
Foo.TryParse(string s, out Foo result)
Methode und ich bin mir nicht sicher über den Rückgabewert. Ich könnte bool
wie .NETs eigene TryParse
Methode verwenden, aber das würde keinen Hinweis auf die Art des Fehlers geben, auf den genauen Grund, warum s
nicht in a analysiert werden konnte Foo
. (Zum Beispiel s
könnte Bar
eine nicht übereinstimmende Klammer oder die falsche Anzahl von Zeichen oder eine ohne entsprechende Baz
usw. vorhanden sein.)
Als Benutzer von APIs mag ich Methoden nicht, die nur einen Booleschen Wert für Erfolg / Misserfolg zurückgeben, ohne mir zu sagen, warum der Vorgang fehlgeschlagen ist. Dies macht das Debuggen zu einem Ratespiel, und das möchte ich auch den Clients meiner Bibliothek nicht aufzwingen.
Ich kann mir viele Problemumgehungen für dieses Problem vorstellen (Statuscodes zurückgeben, eine Fehlerzeichenfolge zurückgeben, eine Fehlerzeichenfolge als out-Parameter hinzufügen), aber alle haben ihre jeweiligen Nachteile, und ich möchte auch mit den Konventionen von konsistent bleiben das .NET Framework .
Meine Frage lautet also wie folgt:
Gibt es in .NET Framework Methoden, die (a) Eingaben analysieren, ohne Ausnahmen auszulösen, und (b) immer noch detailliertere Fehlerinformationen zurückgeben als ein einfacher wahr / falsch-Boolescher Wert?
quelle
Parse()
.Antworten:
Ich würde empfehlen, das Monadenmuster für Ihren Rückgabetyp zu verwenden.
ParseResult<Foo> foo = FooParser.Parse("input");
Beachten Sie auch, dass es nicht in der Verantwortung von Foo liegen sollte, herauszufinden, wie es aus Benutzereingaben analysiert werden soll, da dies Ihre Domain-Schicht direkt an Ihre UI-Schicht bindet und auch gegen das Prinzip der Einzelverantwortung verstößt.
Foo
Abhängig von Ihrem Anwendungsfall können Sie auch eine Analyseergebnisklasse erstellen, die spezifisch für die Verwendung von Generika ist, anstatt diese zu verwenden.Eine foo-spezifische Analyseergebnisklasse könnte ungefähr so aussehen:
Hier ist die Monadenversion:
Mir sind keine Methoden im .net-Framework bekannt, die detaillierte Analysefehlerinformationen zurückgeben.
quelle
Foo.ToString
und zu habenFoo.Parse
.Func<T>
würde diese Kriterien erfüllen, wenn Sie sie inT
die benötigten Informationen aufnehmen. Die Rückgabe detaillierter Fehlerinformationen liegt weitgehend bei Ihnen. Haben Sie darüber nachgedacht, ein zu verwendenMaybe<T>
? Siehe mikhail.io/2016/01/monads-explained-in-csharpSie können sich ModelState im MVC-Framework ansehen . Es stellt eine versuchte Analyse einiger Eingaben dar und kann eine Sammlung von Fehlern enthalten.
Ich glaube jedoch nicht, dass es in der .net-BCL ein wiederkehrendes Muster dafür gibt, da Ausnahmen - zum Guten oder Schlechten - das etablierte Muster für die Meldung von Fehlerbedingungen in .net sind. Ich denke, Sie sollten einfach Ihre eigene Lösung implementieren, die zu Ihrem Problem passt, zum Beispiel eine
ParseResult
Klasse mit zwei Unterklassen,SuccessfulParse
undFailedParse
woSuccessfulParse
eine Eigenschaft mit dem analysierten Wert undFailedParse
eine Fehlermeldungseigenschaft hat. Die Kombination mit dem Mustervergleich in C # 7 könnte ziemlich elegant sein.quelle
Ich habe ähnliche Probleme mit dem Wunsch, eine
TryParse/Convert/etc.
Methode zu verwenden , bei der ich manchmal wissen muss, wie und warum sie fehlgeschlagen ist.Am Ende habe ich mich davon inspirieren lassen, wie einige Serializer mit Fehlern umgehen und Ereignisse verwenden. Auf diese Weise
TryX(..., out T)
sieht die Syntax für meine Methode so sauber aus wie jede andere und gibt zuverlässig eine einfache zurück,false
wie das Muster impliziert.Wenn ich jedoch weitere Details benötigen möchte, füge ich einfach einen Ereignishandler hinzu und erhalte die gewünschten Ergebnisse in einem Paket, das so komplex oder einfach ist, wie ich möchte (siehe
MyEventArgs
unten). Fügen Sie es einer Liste von Zeichenfolgen hinzu, fügen Sie eine hinzuExceptionDispatchInfo
und erfassen Sie Ausnahmen. Lassen Sie den Anrufer entscheiden, ob und wie er mit etwas umgehen möchte, das schief geht.quelle