string s1 = "abc";
string s2 = "ab";
string s3 = s2 + "c";
Console.WriteLine(string.IsInterned(s3));           // abc
Console.WriteLine(String.ReferenceEquals(s1, s3));  // False
我只是不明白为什么 s3 实习,但这ReferenceEquals是假的。
他们在实习生池中有两个副本吗?
提前致谢。
string s1 = "abc";
string s2 = "ab";
string s3 = s2 + "c";
Console.WriteLine(string.IsInterned(s3));           // abc
Console.WriteLine(String.ReferenceEquals(s1, s3));  // False
我只是不明白为什么 s3 实习,但这ReferenceEquals是假的。
他们在实习生池中有两个副本吗?
提前致谢。
它们是单独的参考。该字符串"abc"被保留,因为它是一个文字字符串。
该表达式s2 + "c"被编译为string.Concat(s2, "c").. ,这会产生一个新的(和单独的)字符串引用。
这是因为虽然该字符串的值确实是实习的(因为文字“abc”),但它与实习字符串不是同一个实例,而是由 + 运算符生成的实例。
String.ReferenceEquals(s1, string.IsInterned(s3));
会返回真
string.IsInterned当被调用时,基本上存在三种不同的情况。为了说明,这里有一个测试方法:
static void MyInternCheck(string str)
{
  var test = string.IsInterned(str);
  if ((object)test == (object)str)
    Console.WriteLine("Yes, your string instance is in the intern pool");
  else if (test == str)
    Console.WriteLine("An instance with the same value exists in the intern pool, but you have a different instance with that value");
  else if (test == null)
    Console.WriteLine("No instance with that value exists in the intern pool");
  else
    throw new Exception("Unexpected intern pool answer");
}
您可以使用此代码“击中”所有三种情况:
static void Main()
{
  string x = "0";
  MyInternCheck(x);
  string y = (0).ToString(CultureInfo.InvariantCulture);
  MyInternCheck(y);
  string z = (1).ToString(CultureInfo.InvariantCulture);
  MyInternCheck(z);
}
输出:
是的,您的字符串实例在实习生池中 实习池中存在具有相同值的实例,但您有具有该值的不同实例 实习生池中不存在具有该值的实例
由于"0"程序文本中提到了文字,"0"因此实习池中将存在一个带值的字符串实例。该变量x是对该实例的引用。
该变量y具有与 相同的值,x但直到运行时才计算(C# 编译器不会猜测int.ToString(IFormatProvider)可能返回的内容)。因此,yis 是另一个实例而不是 is x。
该变量z的值在实习生池中找不到。