#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, и что день находится в допустимом диапазоне для этого конкретного месяца.