实习生字符串字面量的误解

本文关键字:误解 字符串 实习生 | 更新日期: 2023-09-27 18:19:14

我不明白:

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

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

例如,如果将相同的字面值字符串赋值给多个变量时,运行时检索对字面量的相同引用从内部池中取出字符串,并将其分配给每个变量。

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

  • 如果是默认的,那么我为什么要使用intern呢?

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

    Console.WriteLine("lalala");

1)我会在内存中得到1000次"拉拉"吗?(不使用intern…)

2)"lalala"最终会被取消吗?

3)"拉拉"已经被拘禁了吗?如果是,为什么我需要从池中"得到"它,而不是再写一次"lalala"?

实习生字符串字面量的误解

字符串字面值被自动存储(因此,如果代码包含"lalala" 1000次,则只存在一个实例)。

这样的字符串不会被GC化,任何时候它们被引用,引用都将是内部引用。


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

实习是发生在幕后的事情,所以你作为一个程序员永远不必担心它。你一般不需要往池子里放任何东西,或者从池子里拿任何东西。就像垃圾收集一样:您永远不必调用它,也不必担心它可能会发生,或者担心它可能不会发生。(嗯,在99.999%的情况下。剩下的0.001%是在你做非常奇怪的事情的时候。

编译器会处理包含在源文件中的所有字符串字面值,所以"lalala"将被存储,而不需要你做任何事情,或者对此事有任何控制。当你在程序中引用"lalala"时,编译器会确保从内部池中获取它,同样不需要你做任何事情,也不需要控制这件事。

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


编辑

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

因此,假设您正在从字符串s的文件中读取令牌,并且您有以下形式的switch语句:
switch( s )
{
    case "cat": ....
    case "dog": ....
    case "tod": ....
}

字符串字面量"cat","dog","tod"都被拘禁了,但是你把它们每一个都和没有被拘禁的s进行比较,所以你没有从实习生群体中获益。如果在switch语句之前调用s,那么由switch语句完成的比较将会快得多。

当然,如果你的文件有可能包含垃圾,那么你不希望这样做,因为加载大量随机字符串到内部池肯定会杀死你的程序的性能,并最终耗尽内存。