189 Stimmen

Testen, ob string eine guid ist, ohne Ausnahmen auszulösen?

Ich möchte versuchen, eine Zeichenkette in eine Guid zu konvertieren, aber ich möchte mich nicht auf das Abfangen von Ausnahmen verlassen (

  • aus Leistungsgründen - Ausnahmen sind teuer
  • aus Gründen der Benutzerfreundlichkeit - der Debugger wird eingeblendet
  • aus gestalterischen Gründen - das Erwartete ist nicht außergewöhnlich

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, mit RegEx, aber da die guid kann Klammer umschlossen, Klammer umschlossen, keine umschlossen, macht es schwer.

Außerdem dachte ich, dass bestimmte Guid-Werte ungültig sind(?)


Aktualisierung 1

ChristianK hatte eine gute Idee, nur FormatException und nicht alle. Das Code-Beispiel in der Frage wurde geändert, um den Vorschlag aufzunehmen.


Aktualisierung 2

Warum sich über ausgelöste Ausnahmen Gedanken machen? Erwarte ich wirklich so oft ungültige GUIDs?

Die Antwort lautet ja . Deshalb verwende ich TryStrToGuid - ich am in Erwartung schlechter Daten.

Beispiel 1 Namespace-Erweiterungen können durch Anhängen einer GUID an einen Ordnernamen angegeben werden . Ich könnte die Ordnernamen analysieren und prüfen, ob der Text nach dem letzten . 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 könnte einen stark genutzten Webserver betreiben, der die Gültigkeit einiger zurückgesendeter Daten überprüfen möchte. Ich möchte nicht, dass ungültige Daten 2-3 Größenordnungen mehr Ressourcen binden als nötig.

Beispiel 3 Möglicherweise analysiere ich einen von einem Benutzer eingegebenen Suchausdruck.

enter image description here

Wenn sie GUIDs eingeben, möchte ich sie speziell verarbeiten (z. B. speziell nach diesem Objekt suchen oder diesen speziellen Suchbegriff im Antworttext hervorheben und formatieren).


Update 3 - Leistungsvergleiche

Test zur Umwandlung 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

p.s. Ich sollte mich für eine Frage nicht rechtfertigen müssen.

0 Stimmen

Ich weiß nicht, die Antwort auf diese ein, aber für was es wert ist, Sie haben Recht, nicht zu wollen, ein Try/Catch-Block hier zu verwenden. Es braucht eine Menge Berechnungen, um die Kosten für das Abfangen einer Ausnahme aufzuwiegen, und try/catch ist nicht für einen normalen Programmablauf geeignet! Natürlich nur, wenn Sie nicht viele Ausnahmen in diesem Code abfangen müssen, es ist nicht wirklich eine große Sache .

7 Stimmen

Warum in aller Welt ist dies ein Gemeinschafts-Wiki?

38 Stimmen

Sie haben Recht, Sie sollten no eine Frage rechtfertigen müssen. Dennoch habe ich die Begründung mit Interesse gelesen (da sie dem Grund, warum ich dies hier lese, sehr ähnlich ist). Also, danke für die tolle Begründung.

2voto

Ilya Ryzhenkov Punkte 11342

Soweit ich weiß, gibt es so etwas wie Guid.TryParse in der mscrolib nicht. Laut Reference Source hat der Guid-Typ einen mega-komplexen Konstruktor, der alle Arten von Guid-Formaten prüft und versucht, sie zu parsen. Es gibt keine Hilfsmethode, die Sie aufrufen können, auch nicht über Reflection. Ich denke, Sie müssen nach Guid-Parsern von Drittanbietern suchen oder Ihre eigenen schreiben.

2voto

Michael Burr Punkte 320591

Führen Sie die potenzielle GUID durch ein RegEx oder einen benutzerdefinierten Code, der eine Plausibilitätsprüfung durchführt, um sicherzustellen, dass die Zeichenkette zumindest wie eine GUID aussieht und nur aus gültigen Zeichen besteht (und vielleicht auch, dass sie in das Gesamtformat zu passen scheint). Wenn der String die Prüfung nicht besteht, wird ein Fehler zurückgegeben - das wird wahrscheinlich die meisten ungültigen Strings aussortieren.

Dann konvertieren Sie die Zeichenfolge, wie Sie oben haben, immer noch die Ausnahme für die wenigen ungültigen Zeichenfolgen, die durch die Sanity-Check erhalten.

Jon Skeet hat eine Analyse für etwas Ähnliches für das Parsen von Ints gemacht (bevor TryParse im Framework war): Prüfung, ob ein String in Int32 konvertiert werden kann

Da jedoch AnthonyWJones darauf hingewiesen, dass Sie sich wahrscheinlich keine Sorgen machen sollten.

1voto

rupello Punkte 8075
 bool IsProbablyGuid(string s)
    {
        int hexchars = 0;
        foreach(character c in string s)
        {
           if(IsValidHexChar(c)) 
               hexchars++;          
        }
        return hexchars==32;
    }

0 Stimmen

"-" "{" "}"(" und ")" sind keine gültigen Hex-Zeichen, aber in einer guid-Zeichenkette sind sie gültig.

2 Stimmen

Und dieser Code funktioniert perfekt, wenn die Eingabe-Guid-Zeichenfolge diese Nicht-Hex-Zeichen enthält

1voto

THX-1138 Punkte 20552
  • Reflektor holen
  • copy'n'paste Guid's .ctor(String)
  • jedes Vorkommen von "throw new ..." durch "return false" ersetzen.

Guid's ctor ist so ziemlich eine kompilierte Regex, so dass Sie genau das gleiche Verhalten ohne Overhead der Ausnahme zu erhalten.

  1. Handelt es sich dabei um ein Reverse Engineering? Ich denke schon, und als solches könnte es illegal sein.
  2. Bricht ab, wenn sich die GUID-Form ändert.

Eine noch coolere Lösung wäre es, eine Methode dynamisch zu instrumentieren, indem man "throw new" on the fly ersetzt.

1 Stimmen

Ich habe versucht, den Code von ctor zu stehlen, aber er verweist auf viele interne private Klassen, um seine Unterstützungsarbeit auszuführen. Glauben Sie mir, das war mein erster Versuch.

1voto

Ich stimme für den GuidTryParse-Link, der oben von Jon oder eine ähnliche Lösung (IsProbablyGuid). Ich werde eine solche Lösung für meine Conversion-Bibliothek schreiben.

Ich finde es total blöd, dass diese Frage so kompliziert sein muss. Das "is"- oder "as"-Schlüsselwort wäre völlig in Ordnung, WENN eine Guid null sein könnte. Aber aus irgendeinem Grund, auch wenn SQL Server damit einverstanden ist, ist .NET es nicht. Und warum? Was ist der Wert von Guid.Empty? Das ist einfach ein dummes Problem, das durch das Design von .NET entstanden ist, und es ärgert mich wirklich, wenn die Konventionen einer Sprache sich selbst im Weg stehen. Die beste Antwort war bisher die Verwendung von COM Interop, weil das Framework nicht elegant damit umgeht? "Kann diese Zeichenkette eine GUID sein?" sollte eine Frage sein, die leicht zu beantworten ist.

Sich darauf zu verlassen, dass die Ausnahme ausgelöst wird, ist in Ordnung, bis die Anwendung ins Internet geht. An diesem Punkt habe ich mich gerade für einen Denial-of-Service-Angriff bereit gemacht. Selbst wenn ich nicht "angegriffen" werde, weiß ich, dass irgendein Yahoo mit der URL herumspielen wird, oder dass meine Marketingabteilung vielleicht einen fehlerhaften Link verschicken wird, und dann muss meine Anwendung einen ziemlich heftigen Leistungsabfall erleiden, der den Server zum Absturz bringen könnte, weil ich meinen Code nicht für ein Problem geschrieben habe, das nicht auftreten sollte, von dem wir aber alle wissen, dass es auftreten wird.

Dies verwischt die Linie ein bisschen auf "Exception" - aber unterm Strich, auch wenn das Problem selten ist, wenn es oft genug in einer kurzen Zeitspanne, dass Ihre Anwendung abstürzt Wartung der Fänge von ihm alle passieren kann, dann denke ich, eine Ausnahme zu werfen ist schlechte Form.

TheRage3K

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X