Regex против Tryparse, что является лучшим в производительности - PullRequest
7 голосов
/ 19 апреля 2011

В моем проекте ASP.net мне нужно проверить некоторые основные типы данных для пользовательского ввода.Типы данных: числовые, десятичные, дата-время и т. Д.

Какой наилучший подход я бы выбрал с точки зрения производительности?Это нужно сделать Regex.IsMatch() или TryParse()?

Заранее спасибо.

Ответы [ 4 ]

9 голосов
/ 19 апреля 2011

TryParse и Regex.IsMatch используются для двух принципиально разных вещей. Regex.IsMatch сообщает вам, соответствует ли рассматриваемая строка некоторому конкретному шаблону. Возвращает ответ да / нет. TryParse на самом деле преобразует значение, если это возможно, и сообщает вам, удалось ли оно.

Если вы не очень осторожны при создании регулярного выражения, Regex.IsMatch может вернуть true, когда TryParse вернет false. Например, рассмотрим простой случай разбора byte. С TryParse у вас есть:

byte b;
bool isGood = byte.TryParse(myString, out b);

Если значение в myString находится в диапазоне от 0 до 255, TryParse вернет true.

Теперь давайте попробуем с Regex.IsMatch. Давайте посмотрим, каким должно быть это регулярное выражение? Мы не можем просто сказать @"\d+" или даже @\d{1,3}". Задание формата становится очень сложной работой. Вы должны обрабатывать начальные 0, начальные и конечные пробелы и разрешать 255, но не 256.

И это только для анализа 3-значного числа. Правила становятся еще сложнее, когда вы анализируете int или long.

Регулярные выражения отлично подходят для определения формы . Они сосут, когда дело доходит до определения значения . Поскольку все наши стандартные типы данных имеют ограничения, определение его значения является частью выяснения, является ли число допустимым.

Вам лучше использовать TryParse всякий раз, когда это возможно, хотя бы для того, чтобы избавить себя от головной боли, пытаясь придумать надежное регулярное выражение, которое выполнит проверку. Вполне вероятно (я бы сказал, почти наверняка), что конкретный TryParse для любого из нативных типов будет выполняться быстрее, чем эквивалентное регулярное выражение.

Выше говорилось, что я, вероятно, потратил больше времени на этот ответ, чем ваша веб-страница потратит на выполнение вашего TryParse или Regex.IsMatch - всего за всю свою жизнь. Время выполнения этих задач настолько мало в контексте всего остального, что делает ваш веб-сайт, и каждый раз, когда вы тратите на размышления о проблеме, теряется.

Используйте TryParse, если можете, потому что это проще. В противном случае используйте Regex.

4 голосов
/ 04 декабря 2012

Не пытайтесь сделать так, чтобы регулярные выражения делали все.

Иногда простое регулярное выражение получит вас на 90% пути, а чтобы сделать все, что вам нужно, сложность возрастает в десять и более раз.

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

Возьмите, например, дату, используйте регулярное выражение для проверкисовпадение в формате даты, а затем используйте группы захвата для проверки значений отдельных значений.

4 голосов
/ 19 апреля 2011

Как сказали бы другие, лучший способ ответить на это - это измерить;)

    static void Main(string[] args)
    {

        List<double> meansFailedTryParse = new List<double>();
        List<double> meansFailedRegEx = new List<double>();
        List<double> meansSuccessTryParse = new List<double>();
        List<double> meansSuccessRegEx = new List<double>();


        for (int i = 0; i < 1000; i++)
        {


            string input = "123abc";

            int res;
            bool res2;
            var sw = Stopwatch.StartNew();
            res2 = Int32.TryParse(input, out res);
            sw.Stop();
            meansFailedTryParse.Add(sw.Elapsed.TotalMilliseconds);
            //Console.WriteLine("Result of " + res2 + " try parse :" + sw.Elapsed.TotalMilliseconds);

            sw = Stopwatch.StartNew();
            res2 = Regex.IsMatch(input, @"^[0-9]*$");
            sw.Stop();
            meansFailedRegEx.Add(sw.Elapsed.TotalMilliseconds);
            //Console.WriteLine("Result of " + res2 + "  Regex.IsMatch :" + sw.Elapsed.TotalMilliseconds);

            input = "123";
            sw = Stopwatch.StartNew();
            res2 = Int32.TryParse(input, out res);
            sw.Stop();
            meansSuccessTryParse.Add(sw.Elapsed.TotalMilliseconds);
            //Console.WriteLine("Result of " + res2 + " try parse :" + sw.Elapsed.TotalMilliseconds);


            sw = Stopwatch.StartNew();
            res2 = Regex.IsMatch(input, @"^[0-9]*$");
            sw.Stop();
            meansSuccessRegEx.Add(sw.Elapsed.TotalMilliseconds);
            //Console.WriteLine("Result of " + res2 + "  Regex.IsMatch :" + sw.Elapsed.TotalMilliseconds);
        }

        Console.WriteLine("Failed TryParse mean execution time     " + meansFailedTryParse.Average());
        Console.WriteLine("Failed Regex mean execution time        " + meansFailedRegEx.Average());

        Console.WriteLine("successful TryParse mean execution time " + meansSuccessTryParse.Average());
        Console.WriteLine("successful Regex mean execution time    " + meansSuccessRegEx.Average());
    }
}
1 голос
/ 19 апреля 2011

Я думаю, что TryParse быстрее, но, что более важно, он более выразителен.

Регулярные выражения могут быть довольно уродливыми, если учесть все допустимые значения для каждого типа данных, который вы используете. Например, с DateTime вы должны убедиться, что месяц находится в диапазоне от 1 до 12, и что день находится в допустимом диапазоне для этого конкретного месяца.

...