Регулярное выражение против Tryparse, какое лучшее по производительности

#c# #asp.net #regex #performance #tryparse

#c# #asp.net #регулярное выражение #Производительность #попробуйте проанализировать

Вопрос:

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

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

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

Комментарии:

1. Вас действительно волнует? По сравнению со всем остальным asp.net какой-либо из двух подходов кажется незначительным с точки зрения влияния на производительность.

2. Использование (Ajax Control Toolik)[ ajaxcontroltoolkit.codeplex.com /] и будьте счастливы.

3. Используйте то, что наиболее подходит / проще всего поддерживать. Производительность в этом случае не является проблемой 🙂

Ответ №1:

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

Если вы не будете очень осторожны при создании регулярного выражения, Regex.IsMatch можете вернуть, true когда TryParse вернется false . Для примера рассмотрим простой случай синтаксического анализа a 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 —total на протяжении всего срока службы. Время на выполнение этих действий настолько мало в контексте всего остального, что делает ваш веб-сайт, любое время, которое вы тратите на обдумывание проблемы, тратится впустую.

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

Ответ №2:

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

     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. tl; dr для тех, кому действительно нужен ответ: int.TryParse() всегда быстрее, чем Regex.IsMatch() (на порядок больше so). Это также быстрее, чем объект Regex, созданный с помощью RegexOptions.Compiled . Убедитесь, что вы используете соответствующий класс (например, ulong ) для вашей ситуации, в зависимости от длины ваших чисел, и имейте в виду, что decimal.TryParse() это значительно медленнее, чем int.TryParse() . Если ни один из этих способов не подходит для вас, stringVariable.All(char.IsDigit) обеспечивает приемлемую золотую середину с точки зрения производительности, а также приятен и лаконичен.

Ответ №3:

Не пытайтесь заставить регулярные выражения делать все.

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

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

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

Ответ №4:

Я бы предположил, что TryParse быстрее, но, что более важно, он более выразительный.

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