【问题标题】:Intern string literals misunderstanding?实习生字符串文字误解?
【发布时间】:2012-01-31 07:32:33
【问题描述】:

我不明白:

MSDN 说

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

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

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

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

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

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

    Console.WriteLine("lalala");

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

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

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

我有点困惑。

【问题讨论】:

    标签: c# .net string-interning


    【解决方案1】:

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

    这样的字符串不会被 GC'd 并且任何时候他们被引用,引用将是被实习的。


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

    【讨论】:

    • 那么,如果 string.intern("lalala") 自动从池中获取,我为什么还要使用它呢?我可以使用“lalala”....请澄清...:) toda。
    • @RoyiNamir - 添加了一些关于 string.Intern 的信息。希望澄清一点。
    • 一如既往地感谢您。 -第二部分为我澄清了一些事情。
    • @RoyiNamir - "aaa" 是一个字符串文字。它会被拘留,不会被 GC 处理。
    • @RoyiNamir - 字符串文字将是程序中存在的字符串编译时
    【解决方案2】:

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

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

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


    编辑

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

    因此,假设您正在从字符串 s 中的文件中读取标记,并且您有一个如下形式的 switch 语句:

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

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

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

    【讨论】:

    • the compiler makes sure to fetch it from the intern pool ...所以我什么时候要明确使用 string.intern ??
    • @Oded 已经回答了这个问题。我将尝试在我的回答中举一个例子。
    • 非常感谢您提供的扩展示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-11
    • 1970-01-01
    • 2010-09-25
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    相关资源
    最近更新 更多