-1

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);
        }
    }
}
GMAN
  • 132
  • 2
  • 9
  • 3
    Can you explain why you want to *avoid* that *highly desirable thing*? String reference identity is usually considered to be a big win, not something to avoid. What are you doing that you want to avoid it? – Eric Lippert Dec 12 '11 at 23:45
  • Other posters are correct. 1) This behaviour is caused by string interning 2) You most likely *want* things to work this way. However, if you are positive that you don't want this behaviour, you can turn it off by using this attribute on your assembly: `[assembly: CompilationRelaxations(CompilationRelaxations.NoStringInterning)]` More info at http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.compilationrelaxations(VS.80).aspx – Dyppl Dec 13 '11 at 07:57
  • I want to thank all of the posters here. I am not really good at understanding all of the nuances of string management in C#. Thanks for all of the explanations. And @Eric as long as it always works you are right I wouldn't want to avoid this highly desirable thing! – GMAN Apr 03 '18 at 12:27

4 Answers4

4

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.

svick
  • 236,525
  • 50
  • 385
  • 514
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.

Mike Bailey
  • 12,479
  • 14
  • 66
  • 123
  • 1
    Are you sure it is interning in this specific case? I can imagine the compiler just merging 2 constants. – H H Dec 12 '11 at 23:48
  • @HenkHolterman, I think you're right and this answer is wrong. See my answer. – svick Dec 13 '11 at 12:41
0

Because strings are immutable.

svick
  • 236,525
  • 50
  • 385
  • 514
Tomas Voracek
  • 5,886
  • 1
  • 25
  • 41
  • @PaulRuane: The fact that strings are immutable is highly relevant; the fact that strings are immutable is *what allows us to intern them*. – Eric Lippert Dec 12 '11 at 23:42
  • Though that is not a bad article for this topic, this article actually addresses the subject at hand more directly: http://blogs.msdn.com/b/ericlippert/archive/2009/09/28/string-interning-and-string-empty.aspx – Eric Lippert Dec 12 '11 at 23:44
  • @Eric I knew that it is somewhere on your blog, i couldn't find it, too many awesome posts. – Tomas Voracek Dec 12 '11 at 23:45
0

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.

competent_tech
  • 44,465
  • 11
  • 90
  • 113