为什么字符串实习,但有不同的引用

本文关键字:引用 字符串 为什么 | 更新日期: 2023-09-27 17:49:01

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));

将返回true

当调用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");
}

你可以用下面的代码"hit"这三种情况:

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)可能返回的内容)。因此,yx的另一个实例。

变量z有一个在内部池中找不到的值