Почему интернирование строк здесь не работает (или нет)?

Рассмотрим следующий код C#:

  var a = "123";
  var b = 123.ToString();
  Console.WriteLine(a==b);
  Console.WriteLine(ReferenceEquals(a, b));
  Console.WriteLine("a interned? " + string.IsInterned(a));
  Console.WriteLine("b interned? " + string.IsInterned(b));
  Console.WriteLine(
    ReferenceEquals(
      string.IsInterned(a),
      string.IsInterned(b)
      )
    );

Это выводит

True
False
a interned? 123
b interned? 123
True

Все в этом имеет смысл, за исключением того, почему ReferenceEquals(a,b) возвращает false, учитывая, что a был интернирован, а затем b будет ссылаться на a, как указано проверками string.IsInterned.


person Dmitri Nesteruk    schedule 04.10.2019    source источник
comment
codeproject.com/Articles/18714/ См. это для понимания.   -  person JamesS    schedule 04.10.2019
comment
123.ToString(); зависит от CultureInfo.CurrentCulture и поэтому не может вычисляться во время времени компиляции (и, следовательно, интернируется)   -  person Dmitry Bychenko    schedule 04.10.2019
comment
@stuartd не объясняет стажировку   -  person Dmitri Nesteruk    schedule 04.10.2019
comment
Это, конечно, не объясняет, почему строка 123 to не интернирована.   -  person Athanasios Kataras    schedule 04.10.2019
comment
ReferenceEquals сравнивает две строки и, если они обе являются одной и той же строкой в ​​памяти, возвращает true. ЕСЛИ в памяти есть два места, одно для a и одно для b, тогда это возвращает false.   -  person CodeCupboard    schedule 04.10.2019
comment
Я не могу ответить на этот вопрос должным образом, поскольку он сейчас закрыт, но все сводится к следующему: 123.toString() является созданием среды выполнения и, следовательно, не является литералом, поэтому он не интернируется и создается новый объект. То же самое произойдет с построителем строк. Однако значение, представленное новой строкой, интернировано, и поэтому IsInterned возвращает значение.   -  person Athanasios Kataras    schedule 04.10.2019
comment
Правила просты. То, что интернировано, определяется компилятором, он выбирает только строковые литералы. И редкий случай, когда код вызывает String.Intern() явно. Любая строка, сгенерированная в коде, например преобразование int в строку в данном случае, не будет интернирована и, следовательно, будет уникальным объектом. Обязательно сравнивайте строки с помощью == или String.Compare() вместо того, чтобы полагаться на ReferenceEquals().   -  person Hans Passant    schedule 04.10.2019
comment
@HansPassant, но если 123.ToString() не интернирован, то IsInterned() должен был вернуть null, а вместо этого вернул строку.   -  person Dmitri Nesteruk    schedule 07.10.2019
comment
IsInterned() работает иначе. Он просматривает интернированную таблицу в поисках интернированной строки с тем же значением. Да, у вас есть литерал 123 в вашей программе. Немного аварии.   -  person Hans Passant    schedule 07.10.2019