我读过this article,它描述了如何使用.NET正则表达式调用示例与静态方法。
但是,如果变量本身是静态的呢?有没有人知道.NET是否做了任何可能导致内存泄漏的缓存?
澄清一下。举例来说:
public static Regex Foo = new Regex(@"(?:,.*)");
对比:
public static void MyMethod(){
Regex Foo = new Regex(@"(?:,.*)");
}
其中一个比另一个更容易导致记忆问题吗?我知道第二个示例显然会创建更多的示例,但是第一个示例是否需要担心传入字符串的缓存,因为它基本上会永远闲置。
3条答案
按热度按时间ax6ht2ek1#
如果你有一个示例化的Regex对象,并且你只是在它上面调用示例方法,那么缓存(根据提供的文章)将不会发生。如果你创建Regex对象并将其作为静态属性存储在类中,你仍然在处理一个示例化的对象,因此缓存不会发生(>=.net 2.0)。
另一方面,每次调用Regex静态方法(如Regex.Match(“bla”,“bla”))时,解析和编译的正则表达式将被缓存。
编辑
看看您的示例,在这两种情况下都不会发生缓存。然而,如果第二个例子是:
.那么编译后的正则表达式
(?:,.*)
将被缓存,因此您可以高效地对Regex.Match(@"(?:,.*)",...
进行后续调用,而无需重新解析/重新编译表达式(?:,.*)
。我想就内存消耗而言,这几乎等同于保留一个静态示例。另一方面,如果提供给Regex.Match的正则表达式发生了变化,那么将以某种(可能可以忽略不计的)代价生成一个额外的条目。ryevplcw2#
没有“静态示例”这样的东西--只有引用对象的静态 * 变量 *。同一个对象可以被示例变量、局部变量或静态变量引用。它不会改变
Regex
构造函数中的任何代码。uurv41yg3#
在
System.Text.RegularExpressions.Regex
类中,框架将在运行时为您做一些缓存。它在缓存它们之前编译它们。但是,只有在使用static
Regex方法时才能利用缓存,如下所述。这从.NET Framework 1.0开始就存在了,直到今天(目前是.NET 8)仍然存在。只有在以下几种情况下才有意义使用内置缓存:什么时候使用“内置”
Regex
缓存?1.在整个应用程序域中使用的不同正则表达式少于 * 16个。这是因为缓存的正则表达式是有限制的,并且这个值是
Regex
类的静态成员(即,由Regex
的所有示例共享。此限制的大小由Regex.CacheSize属性控制。它的默认值为15(迄今为止,所有.NET版本都是如此)。如果需要,可以更改此值。我通常不建议这样做-见建议#1。1.正则表达式是“常量”--表示它的字符串不一定是常量(尽管这是个好主意),但它在每次调用时都不会改变。
如何使用
Regex
内置缓存?利用缓存的唯一方法是使用
static
方法Regex.IsMatch(...)
或Regex.Match(...)
。在你的例子中,你会这样做:建议
1.我不喜欢把缓存留给框架的想法,主要是因为你可能会在将来的某个时候使用额外的静态正则表达式,在另一个类中使用静态正则表达式,或者在另一个dll中使用静态正则表达式,甚至是你不知道的第三方依赖项!因此,我通常创建一个
static readonly Regex
示例作为使用它的类的成员,并根据需要重用它:1.使用
RegexOptions.Compiled
是一个好主意,因此它被编译为MSIL代码,而不是在运行时被解释。编译的正则表达式以最少的初始化时间为代价,最大限度地提高了运行时性能-请参阅RegexOptions