Ich möchte versuchen, einen String in einen Guid zu konvertieren, möchte mich aber nicht darauf verlassen, Ausnahmen abzufangen (
- Aus Leistungsgründen sind Ausnahmen teuer
- Aus Gründen der Benutzerfreundlichkeit wird der Debugger angezeigt
- aus gestalterischen Gründen - das Erwartete ist keine Ausnahme
Mit anderen Worten der Code:
public static Boolean TryStrToGuid(String s, out Guid value)
{
try
{
value = new Guid(s);
return true;
}
catch (FormatException)
{
value = Guid.Empty;
return false;
}
}
ist nicht geeignet.
Ich würde versuchen, RegEx zu verwenden, aber da die Guid in Klammern umwickelt werden kann, macht es die Klammer, keine umwickelt, schwierig.
Außerdem dachte ich, dass bestimmte Guid-Werte ungültig sind (?)
Update 1
ChristianK hatte eine gute Idee, nur FormatException
alle und nicht alle zu fangen . Das Codebeispiel der Frage wurde geändert, um Vorschläge einzuschließen.
Update 2
Warum sich über ausgelöste Ausnahmen Gedanken machen? Erwarte ich wirklich so oft ungültige GUIDs?
Die Antwort lautet ja . Deshalb habe ich TryStrToGuid bin mit - ich bin erwartete schlechte Daten.
Beispiel 1 Namespace-Erweiterungen können durch Anhängen einer GUID an einen Ordnernamen angegeben werden . Möglicherweise analysiere ich Ordnernamen und überprüfe, ob der Text nach dem Finale angezeigt wird . ist eine GUID.
c:\Program Files
c:\Program Files.old
c:\Users
c:\Users.old
c:\UserManager.{CE7F5AA5-6832-43FE-BAE1-80D14CD8F666}
c:\Windows
c:\Windows.old
Beispiel 2 Ich verwende möglicherweise einen stark genutzten Webserver, der die Gültigkeit einiger zurückgesendeter Daten überprüfen möchte. Ich möchte nicht, dass ungültige Daten Ressourcen um 2-3 Größenordnungen höher binden, als es sein muss.
Beispiel 3 Ich analysiere möglicherweise einen von einem Benutzer eingegebenen Suchausdruck.
Wenn sie GUIDs eingeben, möchte ich sie speziell verarbeiten (z. B. gezielt nach diesem Objekt suchen oder diesen bestimmten Suchbegriff im Antworttext markieren und formatieren).
Update 3 - Leistungsbenchmarks
Testen Sie die Konvertierung von 10.000 guten und 10.000 schlechten Guids.
Catch FormatException:
10,000 good: 63,668 ticks
10,000 bad: 6,435,609 ticks
Regex Pre-Screen with try-catch:
10,000 good: 637,633 ticks
10,000 bad: 717,894 ticks
COM Interop CLSIDFromString
10,000 good: 126,120 ticks
10,000 bad: 23,134 ticks
ps Ich sollte keine Frage rechtfertigen müssen.
4.0
. Deshalb sind die Frage und die akzeptierte Antwort so, wie sie sind.Antworten:
Leistungsbenchmarks
COM Intertop (schnellste) Antwort:
Fazit: Wenn Sie überprüfen müssen, ob eine Zeichenfolge eine Richtlinie ist und Sie Wert auf Leistung legen, verwenden Sie COM Interop.
Wenn Sie eine Guid in der Zeichenfolgendarstellung in eine Guid konvertieren müssen, verwenden Sie
quelle
Sobald .net 4.0 verfügbar ist, können Sie verwenden
Guid.TryParse()
.quelle
Das wird dir nicht gefallen, aber warum denkst du, dass das Fangen der Ausnahme langsamer sein wird?
Wie viele fehlgeschlagene Versuche, eine GUID zu analysieren, erwarten Sie im Vergleich zu erfolgreichen?
Mein Rat ist, die gerade erstellte Funktion zu verwenden und Ihren Code zu profilieren. Wenn Sie feststellen, dass diese Funktion wirklich ein Hotspot ist, beheben Sie sie, jedoch nicht vorher.
quelle
In .NET 4.0 können Sie wie folgt schreiben:
quelle
Ich würde es zumindest umschreiben als:
Sie möchten nicht "ungültige GUID" für SEHException, ThreadAbortException oder andere schwerwiegende oder nicht verwandte Dinge sagen.
Update : Ab .NET 4.0 stehen für Guid neue Methoden zur Verfügung:
Guid.TryParse
Guid.TryParseExact
Wirklich, diese sollten verwendet werden (schon allein deshalb, weil sie nicht "naiv" mit try-catch intern implementiert werden).
quelle
Interop ist langsamer als nur die Ausnahme zu fangen:
Auf dem glücklichen Weg mit 10.000 Guids:
Auf dem unglücklichen Weg:
Es ist konsistenter, aber es ist auch konsistent langsamer. Mir scheint, Sie sollten Ihren Debugger besser so konfigurieren, dass er nur bei nicht behandelten Ausnahmen funktioniert.
quelle
Nun, hier ist der reguläre Ausdruck, den Sie brauchen werden ...
Aber das ist nur für den Anfang. Sie müssen auch überprüfen, ob die verschiedenen Teile wie Datum und Uhrzeit innerhalb akzeptabler Bereiche liegen. Ich kann mir nicht vorstellen, dass dies schneller ist als die Try / Catch-Methode, die Sie bereits beschrieben haben. Hoffentlich erhalten Sie nicht so viele ungültige GUIDs, um diese Art der Überprüfung zu rechtfertigen!
quelle
Wenn Sie sich für den Try / Catch-Ansatz entscheiden, können Sie das Attribut [System.Diagnostics.DebuggerHidden] hinzufügen, um sicherzustellen, dass der Debugger auch dann nicht funktioniert, wenn Sie ihn beim Werfen auf "Break" setzen.
quelle
Zwar ist die Verwendung von Fehlern teurer, aber die meisten Menschen glauben, dass ein Großteil ihrer GUIDs computergeneriert sein wird, sodass a
TRY-CATCH
nicht zu teuer ist, da dies nur Kosten für die GUIDs verursachtCATCH
. Sie können sich dies mit einem einfachen Test der beiden beweisen (Benutzer öffentlich, kein Passwort).Bitte schön:
quelle
Ich hatte eine ähnliche Situation und bemerkte, dass die ungültige Zeichenfolge fast nie 36 Zeichen lang war. Aufgrund dieser Tatsache habe ich Ihren Code ein wenig geändert, um eine bessere Leistung zu erzielen und ihn dennoch einfach zu halten.
quelle
Soweit ich weiß, gibt es in mscrolib nichts wie Guid.TryParse. Laut Referenzquelle verfügt der Guid-Typ über einen mega-komplexen Konstruktor, der alle Arten von Guid-Formaten überprüft und versucht, sie zu analysieren. Es gibt keine Hilfsmethode, die Sie aufrufen können, auch nicht durch Reflexion. Ich denke, Sie müssen nach Guid-Parsern von Drittanbietern suchen oder Ihre eigenen schreiben.
quelle
Führen Sie die potenzielle GUID über eine RegEx oder einen benutzerdefinierten Code aus, der eine Überprüfung der Integrität durchführt, um sicherzustellen, dass der Strig mindestens wie eine GUID aussieht und nur aus gültigen Zeichen besteht (und möglicherweise zum Gesamtformat passt). Wenn die Überprüfung der Integrität nicht bestanden wird, wird ein Fehler zurückgegeben. Dadurch wird wahrscheinlich die überwiegende Mehrheit der ungültigen Zeichenfolgen entfernt.
Konvertieren Sie dann die Zeichenfolge wie oben beschrieben, wobei Sie immer noch die Ausnahme für die wenigen ungültigen Zeichenfolgen abfangen, die die Überprüfung der Integrität durchlaufen.
Jon Skeet hat eine Analyse für etwas Ähnliches zum Parsen von Ints durchgeführt (bevor TryParse im Framework enthalten war): Überprüfen, ob eine Zeichenfolge in Int32 konvertiert werden kann
Wie AnthonyWJones jedoch angedeutet hat, sollten Sie sich darüber wahrscheinlich keine Sorgen machen.
quelle
quelle
Der ctor von Guid ist so ziemlich ein kompilierter regulärer Ausdruck. Auf diese Weise erhalten Sie genau das gleiche Verhalten, ohne die Ausnahme zu überschreiten.
Eine noch coolere Lösung wäre, eine Methode dynamisch zu instrumentieren, indem "neu werfen" im laufenden Betrieb ersetzt wird.
quelle
Ich stimme für den GuidTryParse-Link, der oben von Jon oder einer ähnlichen Lösung (IsProbablyGuid) gepostet wurde. Ich werde eine solche für meine Konvertierungsbibliothek schreiben.
Ich finde es total lahm, dass diese Frage so kompliziert sein muss. Das Schlüsselwort "is" oder "as" wäre in Ordnung, wenn eine Guid null sein könnte. Aber aus irgendeinem Grund ist .NET dies nicht, obwohl SQL Server damit einverstanden ist. Warum? Was ist der Wert von Guid.Empty? Dies ist nur ein dummes Problem, das durch das Design von .NET verursacht wurde, und es nervt mich wirklich, wenn die Konventionen einer Sprache auf sich selbst übergehen. Die bisher leistungsstärkste Antwort war die Verwendung von COM Interop, weil das Framework nicht ordnungsgemäß damit umgeht. "Kann diese Zeichenfolge eine GUID sein?" sollte eine Frage sein, die leicht zu beantworten ist.
Sich auf die ausgelöste Ausnahme zu verlassen, ist in Ordnung, bis die App ins Internet geht. Zu diesem Zeitpunkt habe ich mich gerade auf einen Denial-of-Service-Angriff eingestellt. Selbst wenn ich nicht "angegriffen" werde, weiß ich, dass ein Yahoo mit der URL Affen wird, oder vielleicht sendet meine Marketingabteilung einen fehlerhaften Link, und dann muss meine Anwendung einen ziemlich starken Leistungseinbruch erleiden, den KÖNNTE den Server heruntergefahren, weil ich meinen Code nicht geschrieben habe, um ein Problem zu lösen, das NICHT auftreten SOLLTE, aber wir alle wissen, dass es passieren wird.
Dies verwischt die Zeile bei "Ausnahme" ein wenig - aber unter dem Strich, selbst wenn das Problem selten auftritt, wenn es in kurzer Zeit so oft vorkommen kann, dass Ihre Anwendung abstürzt und die Fänge von allem bedient, dann ist es meiner Meinung nach eine Ausnahme schlechte Form.
TheRage3K
quelle
Wenn TypeOf ctype (myvar, Object) Guid ist, dann .....
quelle
quelle
Mit einer Erweiterungsmethode in C #
quelle