Время жизни скомпилированного регулярного выражения в .Net

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