实习生字符串文字误解?

时间:2012-01-01 07:49:45

标签: c# .net string-interning

我不明白:

MSDN说

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

  

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

     

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

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

  • 如果是默认值,为什么我要使用实习生? (实例将一次......)?

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

    Console.WriteLine( “LALALA”);

1)我会在记忆中得到1000次“lalala”吗? (不使用实习生......)

2)将“lalala”最终Gc'ed?

3)“lalala”是否已被实习?如果确实如此,为什么我需要从池中“获取”它,而不是再次写“lalala”?

我有点困惑。

2 个答案:

答案 0 :(得分:9)

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

此类字符串不会获得GC,并且无论何时引用它们,引用都将是实习的。


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

答案 1 :(得分:5)

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

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

实习池包含一个或多或少固定数量的字符串,通常是非常小的字符串(只是.exe的总大小的一小部分),所以它们永远不会变成垃圾并不重要 - 收集。


编辑

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

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

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

字符串文字“cat”,“dog”,“tod”都已被实习,但是你将它们中的每一个与s进行比较,而s没有被实习,所以你没有收获实习池的好处。如果你在switch语句之前实习{{1}},那么switch语句将要完成的比较会快得多。

当然,如果您的文件可能包含垃圾,那么您不希望这样做,因为将大量随机字符串加载到实习池中肯定会破坏程序的性能,并最终运行记忆力不足。