Why are 2 separate string references equal? In other words why are s and t both the same reference?

佐手、 提交于 2019-12-25 18:44:27

问题


Why are the 2 string references the same? I am trying to write a copy constructor and want to avoid string references that point to the same string.

using System;

namespace StringRefTest
{
    class Program
    {
        public static void Main(string[] args)
        {
            Console.WriteLine("String Test!");

            string s = "f"; // This should be one reference
            string t = "f"; // This should be another

            if (ReferenceEquals(s, t))
                Console.WriteLine("Ref Same"); 
            else
                Console.WriteLine("Ref Not Same"); // Should be true

            // The references are the same

            Console.Write("Press any key to continue . . . ");
            Console.ReadKey(true);
        }
    }
}

回答1:


Contrary to what others said, this behavior is not due to string interning. The compiled assembly's metadata contain a table of string constants used. And the C# compiler is smart enough to notice those two strings are the same and use the same constant for both. If the compiler didn't notice this, string interning would be what makes the difference.

To demonstrate this, I tried running a simple program with and without interning. According to CLR via C#, you can specify the [CompilationRelaxationsAttribute(CompilationRelaxations.NoStringInterning)] attribute on an assembly to suggest turning off string inlining. The C# compiler always emits this attribute, but the CLR v.4.0 honors it only when using ngen. This comes in handy for us:

>interning.exe
s and t are reference equal: True
s is interned: True
t is interned: True

>ngen install interning.exe
Microsoft (R) CLR Native Image Generator - Version 4.0.30319.17020
Copyright (c) Microsoft Corporation.  All rights reserved.
1>    Compiling assembly C:\Users\Svick\AppData\Local\Temporary Projects\interni
ng\bin\Debug\interning.exe (CLR v4.0.30319) ...

>interning.exe
s and t are reference equal: True
s is interned: False
t is interned: False

This proves that string interning is not required for two string constants with the same value to be reference equal.




回答2:


The references are equal because string literals get interned. What you're seeing is the fact that s and t are both being pulled from that string intern pool.

What would be more enlightening would be to called the String.IsInterned function on both:

string s = "f";
string t = "f";

Console.WriteLine("Is Interned: {0}", String.IsInterned(s));
Console.WriteLine("Is Interned: {0}", String.IsInterned(t));

You should see that both strings are in fact interned, meaning that they internally point to the same data and thus have the same reference.

The only reason why we can get away with this is because Strings are immutable within C#, as you can read in the links provided by the other answers.




回答3:


This is the string interning functionality of C#. From MSDN:

When a program declares two or more identical string variables, the compiler stores them all in the same location.




回答4:


Because strings are immutable.



来源:https://stackoverflow.com/questions/8482479/why-are-2-separate-string-references-equal-in-other-words-why-are-s-and-t-both

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!