6

我不明白 :

MSDN 说

http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

因此,具有特定值的文字字符串的实例在系统中只存在一次。

例如,如果您将相同的文字字符串分配给多个变量,则运行时会从实习池中检索对文字字符串的相同引用并将其分配给每个变量。

这种行为是默认的(没有实习生)吗?还是使用实习生方法?

  • 如果它是默认的,那我为什么要使用实习生?(实例已经是一次......)?

  • 如果它不是默认值:如果我写了 1000 次这一行:

    Console.WriteLine("lalala");

1)我会在内存中出现 1000 次“lalala”吗?(不使用实习生...)

2)“lalala”最终会被 Gc'ed 吗?

3) "lalala" 已经被实习了吗?如果是这样,为什么我需要从池中“获取”它,而不仅仅是再次写“lalala”?

我有点困惑。

4

2 回答 2

11

字符串文字会自动被实习(因此,如果您的代码包含“lalala”1000 次,则只会存在一个实例)。

这样的字符串不会被 GC 处理,并且在任何时候引用它们时,引用都将是实习生的。


string.Intern是否存在不是文字的字符串 - 例如来自用户输入或从文件或数据库中读取的字符串,并且您知道这些字符串会经常重复,因此值得在整个过程的生命周期内进行实习。

于 2012-01-01T07:54:59.223 回答
5

实习是在幕后发生的事情,所以你作为程序员永远不必担心它。您通常不必将任何东西放入池中,或从池中获取任何东西。就像垃圾收集一样:您永远不必调用它,或者担心它可能会发生,或者担心它可能不会发生。(嗯,在 99.999% 的情况下。剩下的 0.001% 是当你在做非常奇怪的事情时。)

编译器负责对包含在源文件中的所有字符串文字进行实习,因此“lalala”将被实习,而您无需执行任何操作或对此事进行任何控制。每当您在程序中引用“lalala”时,编译器都会确保从实习生池中获取它,而您无需做任何事情,也无法控制此事。

实习生池包含或多或少固定数量的字符串,通常大小非常小(仅占 .exe 总大小的一小部分),因此它们永远不会被垃圾收集并不重要。


编辑

实习字符串的目的是大大提高某些字符串操作(如 Equals())的执行时间。首先通过引用检查字符串是否相等的Equals()方法String,速度极快;如果引用相等,则true立即返回;如果引用不相等,并且字符串都被实习,那么它false立即返回,因为它们不可能相等,因为实习池中的所有字符串都彼此不同。如果以上都不成立,则继续进行逐个字符串的比较。(实际上,它甚至比这更复杂,因为它还检查字符串的哈希码,但让我们在讨论中保持简单。)

因此,假设您正在从 string 中的文件读取令牌s,并且您有以下形式的 switch 语句:

switch( s )
{
    case "cat": ....
    case "dog": ....
    case "tod": ....
}

字符串文字“cat”、“dog”、“tod”都已被实习,但您将它们中的每一个都与尚未实习的 进行比较s,因此您没有获得实习池的好处。如果你s在 switch 语句之前实习,那么 switch 语句将完成的比较会快很多。

当然,如果您的文件可能包含垃圾,那么您不希望这样做,因为将大量随机字符串加载到实习池中肯定会降低程序的性能,并最终耗尽内存.

于 2012-01-01T08:25:07.613 回答