Chcę spróbować przekonwertować ciąg na Guid, ale nie chcę polegać na wyłapywaniu wyjątków (
- ze względu na wydajność - wyjątki są drogie
- ze względów użyteczności - pojawia się debugger
- ze względów projektowych - oczekiwany nie jest wyjątkowy
Innymi słowy kod:
public static Boolean TryStrToGuid(String s, out Guid value)
{
try
{
value = new Guid(s);
return true;
}
catch (FormatException)
{
value = Guid.Empty;
return false;
}
}
nie jest odpowiedni.
Spróbowałbym użyć RegEx, ale ponieważ GUID może być owinięty w nawiasy, owinięty nawiasami klamrowymi, żaden owinięty, utrudnia.
Dodatkowo myślałem, że niektóre wartości Guid są nieprawidłowe (?)
Aktualizacja 1
ChristianK miał dobry pomysł na złapanie FormatException
, a nie wszystkich. Zmieniono przykładowy kod pytania, aby uwzględnić sugestię.
Aktualizacja 2
Po co martwić się zgłoszonymi wyjątkami? Czy naprawdę tak często oczekuję nieprawidłowych identyfikatorów GUID?
Odpowiedź brzmi: tak . Dlatego używam TryStrToGuid - I am spodziewa złych danych.
Przykład 1 Rozszerzenia przestrzeni nazw można określić, dodając identyfikator GUID do nazwy folderu . Mogę analizować nazwy folderów, sprawdzając, czy tekst po finale . jest 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
Przykład 2 Być może korzystam z intensywnie używanego serwera WWW, który chce sprawdzić poprawność niektórych przesłanych danych. Nie chcę, aby nieprawidłowe dane wiązały zasoby o 2-3 rzędy wielkości wyższe, niż trzeba.
Przykład 3 Mogę analizować wyrażenie wyszukiwania wprowadzone przez użytkownika.
Jeśli wprowadzą identyfikatory GUID, chcę je przetworzyć specjalnie (na przykład wyszukiwanie konkretnego obiektu lub wyróżnienie i sformatowanie tego konkretnego wyszukiwanego terminu w tekście odpowiedzi).
Aktualizacja 3 - Testy wydajności
Przetestuj konwersję 10 000 dobrych przewodników i 10 000 złych przewodników.
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 Nie powinienem uzasadniać pytania.
4.0
. Dlatego pytanie i zaakceptowana odpowiedź są takie, jakie są.Odpowiedzi:
Testy wydajności
COM Intertop (najszybsza) odpowiedź:
Konkluzja: Jeśli chcesz sprawdzić, czy łańcuch jest przewodnikiem i zależy Ci na wydajności, użyj COM Interop.
Jeśli chcesz przekonwertować identyfikator GUID w reprezentacji ciągów na identyfikator GUID, użyj
źródło
Gdy .net 4.0 będzie dostępny, możesz go użyć
Guid.TryParse()
.źródło
Nie spodoba ci się to, ale co sprawia, że myślisz, że złapanie wyjątku będzie wolniejsze?
Ile nieudanych prób parsowania GUID oczekuje się w porównaniu z udanymi?
Moja rada to skorzystanie z właśnie utworzonej funkcji i profilowanie kodu. Jeśli okaże się, że ta funkcja jest naprawdę hotspot następnie go naprawić, ale nie wcześniej.
źródło
W .NET 4.0 możesz pisać w następujący sposób:
źródło
Przynajmniej przepisałbym to jako:
Nie chcesz mówić „nieprawidłowy identyfikator GUID” w przypadku SEHException, ThreadAbortException lub innych krytycznych lub niezwiązanych z tym rzeczy.
Aktualizacja : Począwszy od .NET 4.0, dla Guid dostępny jest nowy zestaw metod:
Guid.TryParse
Guid.TryParseExact
Naprawdę, należy ich użyć (choćby dlatego, że nie są „naiwnie” wdrażane przy użyciu try-catch wewnętrznie).
źródło
Interop jest wolniejszy niż tylko wyłapanie wyjątku:
Na szczęśliwej ścieżce z 10 000 przewodników:
Na nieszczęśliwej ścieżce:
Jest bardziej spójny, ale także konsekwentnie wolniejszy. Wydaje mi się, że lepiej byłoby skonfigurować swojego debuggera tak, aby łamał się tylko w przypadku nieobsługiwanych wyjątków.
źródło
Oto regex, którego będziesz potrzebować ...
Ale to tylko na początek. Będziesz także musiał sprawdzić, czy różne części, takie jak data / czas, mieszczą się w dopuszczalnych zakresach. Nie mogę sobie wyobrazić, aby było to szybsze niż metoda try / catch, którą już zarysowałeś. Mamy nadzieję, że nie otrzymujesz tylu nieprawidłowych identyfikatorów GUID, aby uzasadnić tego rodzaju kontrolę!
źródło
Jeśli wybierasz metodę try / catch, możesz dodać atrybut [System.Diagnostics.DebuggerHidden], aby upewnić się, że debugger się nie psuje, nawet jeśli ustawiłeś go tak, aby był łamany podczas rzutu.
źródło
Chociaż prawdą jest, że używanie błędów jest droższe, większość ludzi uważa, że większość ich identyfikatorów GUID będzie generowana komputerowo, więc
TRY-CATCH
nie jest zbyt droga, ponieważ generuje tylko kosztyCATCH
. Możesz to sobie udowodnić za pomocą prostego testu obu (użytkownik publiczny, bez hasła).Proszę bardzo:
źródło
Miałem podobną sytuację i zauważyłem, że prawie nigdy niepoprawny ciąg 36 znaków. W związku z tym zmieniłem nieco twój kod, aby uzyskać lepszą wydajność, jednocześnie zachowując prostotę.
źródło
O ile mi wiadomo, w mscrolib nie ma czegoś takiego jak Guid.TryParse. Według Source Source typ Guid ma mega-złożony konstruktor, który sprawdza wszystkie rodzaje formatów GUID i próbuje je parsować. Nie ma metody pomocniczej, do której można by zadzwonić, nawet poprzez odbicie. Myślę, że musisz szukać zewnętrznych parserów Guid lub napisać własny.
źródło
Uruchom potencjalny identyfikator GUID za pomocą RegEx lub jakiegoś niestandardowego kodu, który sprawdza poprawność, aby upewnić się, że strig przynajmniej wygląda jak GUID i składa się tylko z prawidłowych znaków (i być może wydaje się, że pasuje do ogólnego formatu). Jeśli nie przejdzie kontroli poprawności, zwróci błąd - prawdopodobnie wyeliminuje to większość nieprawidłowych ciągów.
Następnie przekonwertuj ciąg, jak masz powyżej, wciąż wychwytując wyjątek dla kilku nieprawidłowych ciągów, które przechodzą kontrolę poprawności.
Jon Skeet przeprowadził analizę pod kątem czegoś podobnego do analizowania Ints (zanim TryParse był w frameworku): Sprawdzanie, czy łańcuch można przekonwertować na Int32
Jednak, jak wskazał AnthonyWJones , prawdopodobnie nie powinieneś się tym martwić.
źródło
źródło
Ctor Guida jest właściwie skompilowanym wyrażeniem regularnym, dzięki czemu uzyskasz dokładnie to samo zachowanie bez narzutu wyjątku.
Jeszcze fajniejszym rozwiązaniem byłoby dynamiczne oprzyrządowanie metody, zastępując „rzut nowy” w locie.
źródło
Głosuję na link GuidTryParse opublikowany powyżej przez Jona lub podobne rozwiązanie (IsProbablyGuid). Będę pisać taki jak te dla mojej biblioteki konwersji.
Myślę, że to całkowicie nieprzyjemne, że to pytanie musi być tak skomplikowane. Słowo kluczowe „is” lub „as” byłoby w porządku, JEŚLI Guid mógłby mieć wartość zerową. Ale z jakiegoś powodu, chociaż SQL Server jest z tym w porządku, to .NET nie. Czemu? Jaka jest wartość Guid.Empty? To tylko głupiutki problem stworzony przez .NET. Naprawdę mnie wkurza, gdy konwencja języka narzuca się sama. Jak dotąd najskuteczniejszą odpowiedzią jest użycie COM Interop, ponieważ Framework nie radzi sobie z tym płynnie? „Czy ten ciąg może być identyfikatorem GUID?” powinno być pytaniem, na które łatwo odpowiedzieć.
Poleganie na zgłoszonym wyjątku jest OK, dopóki aplikacja nie przejdzie do Internetu. W tym momencie właśnie przygotowałem się na atak typu „odmowa usługi”. Nawet jeśli nie zostanę „zaatakowany”, wiem, że niektórzy yahoo zamierzają wprowadzić małpy za pomocą adresu URL, a może mój dział marketingu wyśle zniekształcony link, a wtedy moja aplikacja będzie musiała ponieść dość wysoką wydajność, którą MOGŁO przynieść nie działa, ponieważ nie napisałem kodu, aby poradzić sobie z problemem, który NIE POWINIEN się zdarzyć, ale wszyscy wiemy, że się zdarzy.
To nieco zaciera linię w „Wyjątku” - ale dolna linia, nawet jeśli problem jest rzadki, jeśli może się zdarzyć wystarczająco dużo razy w krótkim czasie, że twoja aplikacja zawiesza się, obsługując wszystkie wyłapania, wtedy myślę, że zgłoszenie wyjątku jest zła forma.
TheRage3K
źródło
jeśli typ TypeOf (myvar, Object) jest Guid, to .....
źródło
źródło
Z metodą rozszerzenia w C #
źródło