#.net #regex #lifetime
Вопрос:
У меня есть класс валидатора для проверки правильности числового ввода. При создании объектов класса я передаю точность и масштаб конструктору. В методе этого класса я использую регулярное выражение. Сам шаблон всегда будет одинаковым для любого объекта. Я хочу использовать регулярное выражение наиболее оптимальным способом.
Если я использую его таким образом new Regex (pattern, RegexOptions.Compiled)
в методе проверки, будет ли он компилироваться каждый раз при вызове метода? Будет ли он компилироваться каждый раз при создании объекта класса?
Стоит ли создавать выражение в статическом конструкторе класса с целью его однократной компиляции и использования для всех объектов?
В документации говорится
Вы должны использовать скомпилированные регулярные выражения при относительно частом вызове методов регулярных выражений с определенным регулярным выражением.
Метод проверки будет вызываться часто. Поэтому я думаю, что Регулярное выражение.Совпадение (шаблон, …) мне не подходит.
public class NumberValidator
{
private readonly bool onlyPositive;
private readonly int precision;
private readonly int scale;
public NumberValidator(int precision, int scale = 0, bool onlyPositive = false)
{
this.precision = precision;
this.scale = scale;
this.onlyPositive = onlyPositive;
if (precision <= 0)
throw new ArgumentException();
if (scale < 0 || scale >= precision)
...
}
public bool IsValidNumber(string value)
{
var numberRegex = new Regex(@"^([ -]?)(d )([.,](d ))?$", RegexOptions.Compiled);
var match = numberRegex.Match(value);
...
}
}
или
public class NumberValidator
{
private static readonly Regex numberRegex;
private readonly bool onlyPositive;
private readonly int precision;
private readonly int scale;
static NumberValidator()
{
numberRegex = new Regex(@"^([ -]?)(d )([.,](d ))?$", RegexOptions.Compiled);
}
public NumberValidator(int precision, int scale = 0, bool onlyPositive = false)
{
this.precision = precision;
this.scale = scale;
this.onlyPositive = onlyPositive;
if (precision <= 0)
throw new ArgumentException();
if (scale < 0 || scale >= precision)
...
}
public bool IsValidNumber(string value)
{
var match = numberRegex.Match(value);
...
}
}
Ответ №1:
Компиляция регулярных выражений-дорогостоящая операция, поэтому вы хотите выполнить ее один раз и повторно использовать скомпилированный экземпляр, т. Е. свой 2-й фрагмент. Вы, конечно, не хотите создавать новый скомпилированный экземпляр регулярного выражения каждый раз при вызове вашего IsValidNumber
метода, что, вероятно, будет намного медленнее, чем использование некомпилированного регулярного выражения из-за накладных расходов на компиляцию при каждом вызове.