罕见地背离了我典型的自负,我在这个答案上有点颠倒了自己。
我的原始答案(保存在下面)是基于对 .NET 框架的 1.1 版本的检查。这是非常可耻的,因为在我回答时 .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%,但是当在一组 10,000 个输入字符串上运行 100 次(总共 100 万次操作)时,这只增加了大约半秒)。
在某些情况下,这 20% 的减速仍然很重要。如果您发现自己正在正则表达式数以亿计的字符串,您可能会想尽一切可能提高效率。但我敢打赌,在 99% 的情况下,您使用特定正则表达式的次数不会超过几次,而且您在静态方法中损失的额外毫秒数甚至不会被注意到。
devgeezer 的道具,他在差不多一年前就指出了这一点,尽管似乎没有人注意到。
我的旧答案如下:
静态IsMatch函数定义如下:
public static bool IsMatch(string input, string pattern){
return new Regex(pattern).IsMatch(input);
}
而且,是的,Regex 对象的初始化并非易事。您应该使用静态IsMatch(或任何其他静态Regex 函数)作为您只使用一次的模式的快速快捷方式。如果您要重用该模式,那么重用 Regex 对象也是值得的。
至于您是否应该按照 Jon Skeet 的建议指定 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,编译后的版本胜出。