为什么不对字符串的副本进行实习?

时间:2013-03-01 15:28:45

标签: c#

假设:

        object literal1 = "abc";
        object literal2 = "abc";

        object copiedVariable = string.Copy((string)literal1);

        if (literal1 == literal2)
            Console.WriteLine("objects are equal because of interning");//Are equal

        if(literal1 == copiedVariable)
            Console.WriteLine("copy is equal");
        else
            Console.WriteLine("copy not eq");//NOT equal

这些结果意味着copiedVariable不受字符串实习的影响。为什么?

是否存在这样的情况,即由于某些语言细节而导致具有等效字符串的情况是否有用或是否存在此行为?

2 个答案:

答案 0 :(得分:5)

如果你考虑一下,字符串的实习是一个在编译时在文字上触发的过程。这意味着:

  • 当您将文字分配/绑定到变量
  • 时,它是隐式的
  • 复制引用时隐式(即字符串a = some_other_string_variable;)

另一方面,如果您在运行时通过使用StringBuilder或通过复制创建字符串的实例,那么您必须专门请求实例化它调用String类的Intern方法。

即使在文件的备注部分,也要说明:

  

公共语言运行库通过维护a来保存字符串存储   表,称为实习池,包含单个引用   以编程方式声明或创建的每个唯一文字字符串   你的计划。因此,带有一个文字字符串的实例   特定值仅在系统中存在一次。例如,如果你   将相同的文字字符串分配给多个变量,即运行时   从实习生中检索对文字字符串的相同引用   池并将其分配给每个变量。

String类的Copy方法的文档说明了它:

  

使用与指定值相同的值创建 String的新实例   字符串。

这意味着它不会只返回对同一个字符串的引用(来自实习池)。再说一次,如果确实没有那么多用,那么,那会吗?!

答案 1 :(得分:1)

某些语言要求结果是某些方法/程序的副本。

例如,在substring类型方法中。即使您调用foo.substring(0, foo.length)(以及如何实现stringcopy),语义也将是相同的。

注意:IIRC *,但这不是.NET的string.Substring实现的情况。 MSDN也不是很清楚。 (见下文)

它返回:

  

一个字符串,它等于长度为length的子字符串   在此实例中从startIndex开始,如果startIndex相等则为Empty   到这个实例的长度,长度为零。

它注意到:

  

此方法不会修改当前实例的值。   相反,它返回一个长度为字符的新字符串   当前字符串中的startIndex位置。

<强>更新

我没记错,如果string InternalSubString(int startIndex, int length, bool fAlwaysCopy)不是fAlwaysCopy,它确实会与false进行核对。 Substringfalse传递给此方法。

更新2

看起来string.Copy可以使用InternalSubString并将true传递给前面提到的参数,但是看看反汇编,它似乎使用稍微更优化的版本并可能保存方法调用。

很抱歉有多余的信息。

*我记得的原因是在实施IronScheme的substring程序时,R6RS规范需要复制该程序:)