Why string interned but has different references?

string s1 = "abc";
string s2 = "ab";
string s3 = s2 + "c";

Console.WriteLine(string.IsInterned(s3));           // abc
Console.WriteLine(String.ReferenceEquals(s1, s3));  // False

I just cannot understand why s3 interned, but ReferenceEquals was False.

Dose they have two copies in intern pool?

Thanks in advance.

Answers


There are basically three different situations possible when string.IsInterned is invoked. To illustrate, here is a test method:

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

You can "hit" all three situations with this code:

static void Main()
{
  string x = "0";
  MyInternCheck(x);
  string y = (0).ToString(CultureInfo.InvariantCulture);
  MyInternCheck(y);
  string z = (1).ToString(CultureInfo.InvariantCulture);
  MyInternCheck(z);
}

Output:

Yes, your string instance is in the intern pool
An instance with the same value exists in the intern pool, but you have a different instance with that value
No instance with that value exists in the intern pool

Since the literal "0" is mentioned in the program text, a string instance with value "0" will exist in the intern pool. The variable x is a reference to that instance.

The variable y has the same value as x, but that is not computed until run-time (the C# compiler makes no guesses as to what int.ToString(IFormatProvider) could be returning). As a consequence, y is another instance than is x.

The variable z has a value that is not found in the intern pool.


They are separate references. The string "abc" is interned because it is a literal string.

The expression s2 + "c" is compiled to string.Concat(s2, "c").. which results in a new (and separate) string reference.


This is because while the value of that string is indeed interned (because of the literal "abc"), it is not the same instance as the interned string, rather an instance generated by the + operator.

String.ReferenceEquals(s1, string.IsInterned(s3));

would return true


Need Your Help

paypal, let customer pay half of total price

php paypal

I have an item that costs $500 for example. I wanna let users be able to make partial payments, for example I wanna let them pay 50% of that amount ($250) and the other half is due after a certain ...