简体   繁体   English

String.IsInterned的目的是什么?

[英]What is the purpose of String.IsInterned?

In the String class there is a method IsInterned() . String类中有一个方法IsInterned() I never use this method. 我从不使用这种方法。 Please help me to understand the best uses of this method. 请帮助我了解这种方法的最佳用途。

Consider that interning is an optimisation; 考虑到实习是一种优化; it trades a decrease in some desirable qualities for an increase in others. 它会降低一些理想的品质,以增加其他品质。 In particular interning has the following good qualities: 特别是实习具有以下优点:

  1. Memory is not wasted on duplicate strings. 内存不会浪费在重复的字符串上。
  2. Equality comparison between strings known to both be interned is extremely fast. 两个已知的字符串之间的相等比较非常快。
  3. Equality comparison between strings that happen to be interned is still much faster than if they aren't interned. 恰好被中断的字符串之间的相等比较仍然比没有被中断的字符串快得多。
  4. Other comparisons get a performance benefit in some cases. 在某些情况下,其他比较会获得性能优势。

It has the following bad qualities: 它具有以下不良品质:

  1. Strings are not garbage collected as often (if at all), so memory that could be reclaimed is used on strings that are never seen again, or for a very long time. 字符串不是经常收集的垃圾(如果有的话),因此可以回收的内存用于永远不会再看到的字符串,或者很长时间。 (Intern all your strings and you could end up with really nasty memory use). (实习你所有的字符串,你最终可能会有非常讨厌的内存使用)。

As an optimisation, we use it where the either the good qualities out-weigh the bad or where the bad qualities don't hold (if we know the string is going to be around for the lifetime of the application anyway, or know it will be used many times, then the bad part doesn't hold). 作为一种优化,我们使用它来衡量好的品质或者质量不好的地方(如果我们知道字符串将会在应用程序的整个生命周期中出现,或者知道它会多次使用,然后坏部分不成立)。

And by the same token we don't use it where the bad qualities will out-weigh the good. 并且出于同样的原因,我们不会使用它,因为糟糕的品质会超过好处。 (Most of the time). (大多数时候)。

IsInterned() can be used to find a part-way point. IsInterned()可用于查找部分点。

Consider I have a string property Name : 考虑我有一个字符串属性Name

public string Name { get; set; }

Let's say I know that it's common to look for objects with a given Name , or to try to find objects with the same Name or otherwise do a lot of equality comparisons on it. 假设我知道查找具有给定Name对象是常见的,或者尝试查找具有相同Name对象,或者对其进行大量的相等比较。 OR Let's say I know there will be a lot of other objects with the same Name . 或者假设我知道会有很多其他具有相同Name对象。 OR Both. 或两者。

In these cases I might consider interning: 在这些情况下,我可能会考虑实习:

private string _name;
public string Name
{
  get { return _name; }
  set { _name = string.Intern(value); }
}

Of course, whether this was a good idea or not depends on the good and bad qualities of interning mentioned above. 当然,这是否是一个好主意取决于上面提到的实习的好坏。

In-between using and not using is the possibility: 中间使用和不使用是可能的:

private string _name;
public string Name
{
  get { return _name; }
  set { _name = string.IsInterned(value) ?? value; }
}

Here if the string value is already interned then we the down-sides of interning are already at work and we don't suffer any more, so we take advantage of it. 如果字符串value已经被实习,那么我们实习的下方已经在工作,我们不再受苦,所以我们利用它。 But if value is not already interned then we just use it as-is. 但如果value尚未实现,那么我们只是按原样使用它。

This is also an optimisation, that optimises for a different case. 这也是一种优化,可以针对不同的情况进行优化。 It only benefits if a reasonable number of the values seen are likely to be interned by some other code (or because they match literals in the assembly), otherwise it just wastes time doing lookups. 只有当看到的合理数量的值可能被某些其他代码(或者因为它们与程序集中的文字匹配)有效时,它才会受益,否则它只会浪费时间进行查找。 It's probably less often useful than Intern() which in turn is less often useful than just using the strings and ignoring interning, but that does show a time when it could be useful. 它可能不如Intern()有用,后者反过来不仅仅是使用字符串而忽略实习,但确实显示了它可能有用的时间。

One possible use would be if you want to lock on the string value. 一种可能的用法是如果要锁定字符串值。

In the following: 在下面的:

string s = //get it from somewhere, e.g. a web request
lock (s){
//do something
}

there is a problem, because there might be two different requests for the same string, but they both enter the protected code. 有一个问题,因为对同一个字符串可能有两个不同的请求,但它们都输入受保护的代码。 This is because there might be two different string objects that has the same value. 这是因为可能存在两个具有相同值的不同字符串对象。

However there is something called intern pool, which is a table that contains a single instance of some strings (all the literals are there for example). 但是有一个叫做intern pool的东西,它是一个包含一些字符串实例的表(例如,所有的文字都在那里)。

You can use it to make the locking work: 您可以使用它来锁定工作:

string s = //get it from somewhere, e.g. a web request
lock (string.Intern(s)){
//do something
}

This function would return a reference to a string in the intern pool, which has the same value as s, so is safe for locking. 此函数将返回对实习池中字符串的引用,该字符串与s具有相同的值,因此可以安全地锁定。

The IsIntern function simply checks whether the reference you are holding is a reference to a string on the intern pool. IsIntern函数只检查您持有的引用是否是对实习池中字符串的引用。

请参阅Eric的帖子,我认为这是Intern的最佳解释

String literals in C# are interned (that is, they are stored into an intern pool) so that for each occurrence of the literal there is only one instance. C#中的字符串文字是固定的(也就是说,它们存储在实习池中),因此对于文字的每次出现,只有一个实例。 If you are making your own language (for example some script system), you can use IsInterned and Intern to yield the same thing. 如果您使用自己的语言(例如某些脚本系统),则可以使用IsInterned和Intern来生成相同的内容。

Have a look at this . 看看这个 There actually is a use case in that thread. 实际上该线程中有一个用例。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM