String
类中有一个方法IsInterned()
。我从未使用过这个方法,请帮我理解如何最好地使用它。它还具有以下缺点:
作为一种优化,我们在以下情况下使用字符串驻留:要么优点超过缺点,要么缺点不成立(如果我们知道该字符串在应用程序生命周期内将一直存在,或者知道它将被多次使用,则缺点不成立)。
同样地,我们不会在坏的品质超过好的品质的情况下使用它。(大部分时间是这样的)
IsInterned()
方法可用于找到中间点。
考虑我有一个字符串属性Name
:
public string Name { get; set; }
假设我知道按给定的Name
查找对象很常见,或尝试查找具有相同Name
的对象或对其进行许多等式比较。或者我知道将会有许多其他具有相同Name
的对象。或两者兼而有之。
在这些情况下,我可能考虑使用内部化技术:
private string _name;
public string Name
{
get { return _name; }
set { _name = string.Intern(value); }
}
当然,这是否是一个好主意取决于实习的优点和缺点。
在使用和不使用之间存在可能性:
private string _name;
public string Name
{
get { return _name; }
set { _name = string.IsInterned(value) ?? value; }
}
如果字符串 value
已经被内部化(interned),那么我们就已经避免了内部化的缺点,不会再受到影响,因此我们可以利用它。但是如果 value
没有被内部化,那么我们就直接使用它。
这也是一种优化方法,针对不同的情况进行优化。只有当一定数量的值可能由其他代码内部化(或者因为它们与汇编中的字面量匹配)时,才会受益于这种优化。否则,这只会浪费时间进行查找。它可能比 Intern()
更少使用,而后者又比仅使用字符串而忽略内部化更少使用,但这确实展示出了一种它有用的时候。
如果您想锁定字符串值,其中一个可能的用途是使用它。
接下来的内容如下:
string s = //get it from somewhere, e.g. a web request
lock (s){
//do something
}
存在一个问题,因为可能会有两个不同的请求获取相同的字符串,但它们都进入了受保护的代码。这是因为可能有两个不同的字符串对象具有相同的值。
然而,有一个称为intern池的东西,它是一个包含某些字符串的单个实例的表(例如,所有文字都在其中)。
您可以使用它来使锁定起作用:
string s = //get it from somewhere, e.g. a web request
lock (string.Intern(s)){
//do something
}
这个函数将返回一个字符串池中与s相同值的字符串引用,因此可以安全锁定。
IsIntern
函数仅检查您所持有的引用是否是指向字符串池中的字符串的引用。
C# 中的字符串字面量是被池化(即它们被存储到一个内部池中),因此每个字面量的出现只有一个实例。如果您正在创建自己的语言(例如某些脚本系统),则可以使用 IsInterned 和 Intern 来产生相同的效果。