В редком отклонении от моего типичного эгоизма я как бы переворачиваюсь с этим ответом.
Мой оригинальный ответ, сохраненный ниже, был основан на проверке версии 1.1 .NET Framework. Это довольно постыдно, поскольку .NET 2.0 отсутствовал более трех лет на момент моего ответа и содержал изменения в классе Regex
, которые значительно влияют на разницу между статическими и экземплярами методов.
В .NET 2.0 (и 4.0) статическая функция IsMatch
определяется следующим образом:
public static bool IsMatch(string input, string pattern){
return new Regex(pattern, RegexOptions.None, true).IsMatch(input);
}
Существенная разница здесь в том, что маленький true
в качестве третьего аргумента. Это соответствует параметру с именем «useCache». Если это так, то проанализированное дерево извлекается из кэша при втором и последующем использовании.
Это кэширование поглощает большую часть - но не все - разницы в производительности между статическими и экземплярами методов. В моих тестах статический метод IsMatch
все еще был примерно на 20% медленнее, чем метод экземпляра, но это составляло примерно половину секунды при 100-кратном запуске из набора из 10000 входных строк (всего 1 миллион операций ).
Это замедление на 20% все еще может быть значительным в некоторых сценариях. Если вы обнаружите, что перестраиваете сотни миллионов строк, вы, вероятно, захотите сделать каждый шаг, чтобы сделать его более эффективным. Но я бы поспорил, что в 99% случаев вы используете конкретное регулярное выражение не более нескольких раз, а лишняя миллисекунда, которую вы теряете статическим методом, не будет даже близка к заметной.
Реквизит devgeezer , который указал на это почти год назад, хотя, казалось, никто не заметил.
Мой старый ответ следующий:
Статическая функция IsMatch
определяется следующим образом:
public static bool IsMatch(string input, string pattern){
return new Regex(pattern).IsMatch(input);
}
И, да, инициализация Regex
объекта не тривиальна. Вы должны использовать статические IsMatch
(или любые другие статические Regex
функции) в качестве быстрого ярлыка только для шаблонов, которые вы будете использовать только один раз. Если вы будете использовать шаблон повторно, стоит также повторно использовать объект Regex
.
Относительно того, следует ли указывать RegexOptions.Compiled
, как предполагает Джон Скит, это другая история. Ответ есть: это зависит. Для простых шаблонов или для шаблонов, используемых только несколько раз, может быть быстрее использовать не скомпилированный экземпляр. Вы должны определенно профиль, прежде чем принять решение. Стоимость компиляции объекта регулярного выражения действительно достаточно велика и может не стоить этого.
Возьмем, к примеру, следующее:
const int count = 10000;
string pattern = "^[a-z]+[0-9]+$";
string input = "abc123";
Stopwatch sw = Stopwatch.StartNew();
for(int i = 0; i < count; i++)
Regex.IsMatch(input, pattern);
Console.WriteLine("static took {0} seconds.", sw.Elapsed.TotalSeconds);
sw.Reset();
sw.Start();
Regex rx = new Regex(pattern);
for(int i = 0; i < count; i++)
rx.IsMatch(input);
Console.WriteLine("instance took {0} seconds.", sw.Elapsed.TotalSeconds);
sw.Reset();
sw.Start();
rx = new Regex(pattern, RegexOptions.Compiled);
for(int i = 0; i < count; i++)
rx.IsMatch(input);
Console.WriteLine("compiled took {0} seconds.", sw.Elapsed.TotalSeconds);
При count = 10000
, как указано в списке, второй выход самый быстрый. Увеличьте count
до 100000
, и скомпилированная версия победит.