Проверить, является ли строка guid без исключения? - PullRequest
178 голосов
/ 19 сентября 2008

Я хочу попробовать преобразовать строку в Guid, но я не хочу полагаться на перехват исключений (

  • по соображениям производительности - исключения дорогие
  • по соображениям удобства использования - появляется отладчик
  • по проектным причинам - ожидаемое не исключение

Другими словами код:

public static Boolean TryStrToGuid(String s, out Guid value)
{
    try
    {
        value = new Guid(s);
        return true;
    }
    catch (FormatException)
    {
        value = Guid.Empty;
        return false;
    }
}

не подходит.

Я бы попробовал использовать RegEx, но так как guid может быть заключен в круглые скобки, заключен в скобки, но ни один из них не затруднит.

Кроме того, я думал, что некоторые значения Guid недействительны (?)


Обновление 1

ChristianK неплохо было поймать только FormatException, а не все. Изменен пример кода вопроса, чтобы включить предложение.


Обновление 2

Зачем беспокоиться о брошенных исключениях? Неужели я так часто жду неверных идентификаторов GUID?

Ответ Да . Вот почему я использую TryStrToGuid - я * ожидаю неверных данных.

Пример 1 Расширения пространства имен можно указать, добавив GUID к имени папки . Я мог бы анализировать имена папок, проверяя, является ли текст после окончательного . 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

Пример 2 Возможно, я использую интенсивно используемый веб-сервер, который хочет проверить достоверность некоторых опубликованных данных. Я не хочу, чтобы недействительные данные связывали ресурсы на 2-3 порядка выше, чем нужно.

Пример 3 Возможно, я анализирую поисковое выражение, введенное пользователем.

enter image description here

Если они вводят GUID, я хочу обрабатывать их специально (например, специально искать этот объект или выделять и форматировать этот конкретный поисковый термин в тексте ответа.)


Обновление 3 - тесты производительности

Тест на преобразование 10 000 хороших гидов и 10 000 плохих гидов.

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. Я не должен был обосновывать вопрос.

Ответы [ 18 ]

2 голосов
/ 19 сентября 2008

Насколько я знаю, в mscrolib нет ничего похожего на Guid.TryParse. Согласно Reference Source, тип Guid имеет конструктор мега-сложности, который проверяет все виды форматов guid и пытается их проанализировать. Нет вспомогательного метода, который вы можете вызвать, даже с помощью отражения. Я думаю, что вы должны искать сторонние парсеры Guid или написать свой собственный.

2 голосов
/ 19 сентября 2008

Запустите потенциальный GUID через RegEx или некоторый пользовательский код, который проверяет работоспособность, чтобы убедиться, что стринг, по крайней мере, выглядит как GUID и состоит только из допустимых символов (и, возможно, что он соответствует общему формату). Если он не пройдет проверку исправности, верните ошибку - это, вероятно, отсеет подавляющее большинство недопустимых строк.

Затем преобразуйте строку, как описано выше, по-прежнему перехватывая исключение для нескольких недопустимых строк, которые проходят проверку работоспособности.

Джон Скит сделал анализ для чего-то похожего для разбора Ints (до того, как TryParse был в Framework): Проверка возможности преобразования строки в Int32

Однако, как сказал AnthonyWJones , вам, вероятно, не стоит беспокоиться об этом.

1 голос
/ 23 августа 2009

Я голосую за ссылку GuidTryParse, опубликованную выше Jon или аналогичным решением (IsProbblyGuid). Я напишу такой же для моей библиотеки конверсий.

Я думаю, что это совершенно неубедительно, что этот вопрос должен быть настолько сложным. Ключевое слово "is" или "as" было бы очень хорошо, если бы Guid мог быть нулевым. Но по какой-то причине, хотя SQL Server в порядке с этим, .NET нет. Зачем? Какова стоимость Guid.Empty? Это просто глупая проблема, созданная при разработке .NET, и она действительно беспокоит меня, когда соглашения о языке наступают сами собой. Лучшим ответом на сегодняшний день является использование COM Interop, потому что Framework не справляется с этим изящно? "Может ли эта строка быть GUID?" должен быть вопрос, на который легко ответить.

Можно полагаться на исключение, пока приложение не появится в Интернете. В этот момент я просто настроился на атаку отказа в обслуживании. Даже если я не буду «атакован», я знаю, что некоторые из них собираются поэкспериментировать с URL-адресом, или, возможно, мой отдел маркетинга отправит неверно сформированную ссылку, и тогда мое приложение должно испытать довольно значительный удар по производительности, который МОЖЕТ принести на сервере, потому что я не написал свой код для решения проблемы, которая НЕ ДОЛЖНА произойти, но мы все знаем, что БУДЕТ ПРОИЗОШЛО.

Это немного размывает строку «Исключение», но суть в том, что даже если проблема нечастая, если за короткий промежуток времени может произойти достаточное количество раз, когда ваше приложение аварийно завершает работу, обслуживая все ловушки, тогда я думаю, что исключение - плохая форма.

TheRage3K

1 голос
/ 27 мая 2009
  • Get Reflector
  • copy'n'paste. Guid's .ctor (String)
  • заменить каждое вхождение «throw new ...» на «return false».

ctor Guid - это в значительной степени скомпилированное регулярное выражение, поэтому вы получите точно такое же поведение без дополнительных затрат.

  1. Это реверс-инжиниринг? Я думаю, что это так и может быть незаконным.
  2. Сломается при изменении формы GUID.

Еще более клёвым решением было бы динамическое применение метода, заменив «на лету новым».

1 голос
/ 19 сентября 2008
 bool IsProbablyGuid(string s)
    {
        int hexchars = 0;
        foreach(character c in string s)
        {
           if(IsValidHexChar(c)) 
               hexchars++;          
        }
        return hexchars==32;
    }
0 голосов
/ 20 августа 2009
Private Function IsGuidWithOptionalBraces(ByRef strValue As String) As Boolean
    If String.IsNullOrEmpty(strValue) Then
        Return False
    End If

    Return System.Text.RegularExpressions.Regex.IsMatch(strValue, "^[\{]?[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}[\}]?$", System.Text.RegularExpressions.RegexOptions.IgnoreCase)
End Function


Private Function IsGuidWithoutBraces(ByRef strValue As String) As Boolean
    If String.IsNullOrEmpty(strValue) Then
        Return False
    End If

    Return System.Text.RegularExpressions.Regex.IsMatch(strValue, "^[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}$", System.Text.RegularExpressions.RegexOptions.IgnoreCase)
End Function


Private Function IsGuidWithBraces(ByRef strValue As String) As Boolean
    If String.IsNullOrEmpty(strValue) Then
        Return False
    End If

    Return System.Text.RegularExpressions.Regex.IsMatch(strValue, "^\{[0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12}\}$", System.Text.RegularExpressions.RegexOptions.IgnoreCase)
End Function
0 голосов
/ 20 июля 2017

С методом расширения в C #

public static bool IsGUID(this string text)
{
    return Guid.TryParse(text, out Guid guid);
}
0 голосов
/ 23 мая 2009

если TypeOf ctype (myvar, Object) является Guid, то .....

...