2

Given the following simple .NET code, is there any difference between these two, under the hood with respect to the string "xml"?

if (extension.Equals("xml", StringComparison.OrdinalIgnoreCase))
{
    return FileType.Xml;
}

vs

const string xmlText = "xml";
if (extension.Equals(xmlText, StringComparison.OrdinalIgnoreCase))
{
    return FileType.Xml;
}

Mind you, the word "xml" is never used again in the class. It's literally at that one spot.

I was under the impression that the more recent versions of the .NET compiler converts simple strings like that, to a const (under the hood).

Even more awesome, is that if there's another "xml" string used in another place, the compiler will only make one const creation and both of those references will refer to that single string reference/memory alloc.

So - is there any difference, behind the scenes with respect to performance?

Disclaimer: please no 'micro-optimation' comments. I get that. This is really about understanding things vs trying to micro-optimize one line of code.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111
Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
  • Maybe this helps you: http://broadcast.oreilly.com/2010/08/understanding-c-stringintern-m.html – wkl Feb 23 '17 at 10:58
  • 1
    "when the compiler encounters a constant identifier in C# source code, it substitutes the literal value directly into the intermediate language (IL) code that it produces" This can cause problems when you reference public const from another assembly, then that assembly is recompiled with different values for the const. Because the value was inlined, the code that references it never sees the update. – spender Feb 23 '17 at 11:00
  • 2
    Please read [ask] and share your research. A very relevant term is "string interning", which you must have come across during your research, yet it isn't present in your question. – CodeCaster Feb 23 '17 at 11:00
  • There is no performance difference and as for why would one use `const` **inside** method see [this](http://stackoverflow.com/q/5833912/1997232). TLDR; you can't use `readonly` inside the method and `const` is simply a way to ask compiler "please tell me if I am stupid and will try to modify this variable". – Sinatr Feb 23 '17 at 11:08
  • Just use a decompiler, even ildasm.exe will do. And you'll see that there just is no difference, the C# compiler makes the `const` detail disappear and generates the exact same IL. Use `const` where it makes sense to use a constant. – Hans Passant Feb 23 '17 at 11:12

4 Answers4

5

It is the same for the compiler. Basically both variables have no way of being changed at runtime.

This is an example:

public static void Main()
{
    Console.WriteLine("Hello World");

    const string hello = "Hello World";
    Console.WriteLine(hello);
}

Compiles to:

.method public hidebysig static void  Main() cil managed
  {
    // 
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      "Hello World"
    IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ldstr      "Hello World"
    IL_0011:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_0016:  nop
    IL_0017:  ret
  }

As you can see they are exactly the same. Compiler uses ldstr to push a string object for the literal string.

You can move const string outside method and it won't make a difference, because literals are treated as consts.

FCin
  • 3,804
  • 4
  • 20
  • 49
3

The answer to your question is: No, you will not see a performance increase.

The C# specification explicitly addresses the situation of identical literal strings in Section 2.4.4.5 String Literals:

Each string literal does not necessarily result in a new string instance. When two or more string literals that are equivalent according to the string equality operator (§7.10.7) appear in the same program, these string literals refer to the same string instance.

Additionally, Section 7.19 Constant expressions states:

[The constant expression] is evaluated at compile-time. The compile-time evaluation of constant expressions uses the same rules as run-time evaluation of non-constant expressions, except that where run-time evaluation would have thrown an exception, compile-time evaluation causes a compile-time error to occur.

This indicates that the const and literal strings are treated the same way.

If you inspect the IL output from the compiler, you will discover that const strings produce the same output as using literal strings in their place.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
2

There is no difference due to the fact that literal strings are normally interned by the compiler.

All the following examples will print out true:

  • Example 1:

    const string constHello = "Hello";
    
    void Foo()
    {
        var localHello = "Hello";
        Console.WriteLine(ReferenceEquals(constHello, localHello));
    }
    
  • Example 2:

    string fieldHello = "Hello";        
    
    void Foo()
    {
        var localHello= "Hello";
        Console.WriteLine(ReferenceEquals(fieldHello, localHello));
    }
    
  • Example 3:

    const string constHello = "Hello";
    
    void Foo()
    {
        Console.WriteLine({IsReferenceEquals("Hello")}");
    }
    
    public static bool IsReferenceEquals(string s) => ReferenceEquals(constHello, s);
    

In all cases, there is only one instance of "Hello".

InBetween
  • 32,319
  • 3
  • 50
  • 90
1

Even more awesome, is that if there's another "xml" string used in another place, the compiler will only make one const creation and both of those references will refer to that single string reference/memory alloc.

This is normal behavior since .NET make "string interning" by default so many variables will references the same memory allocation

So .NET automatically performs string interning for all string literals. This is done by means of an intern pool – a special table that stores references to all unique strings.

Only explicitly declared string literals are interned on the compile stage. The strings created at runtime are not checked for being already added to the pool. For example:

Interning example

string s="AB";   //will be interned  
string s1 ="C";    
string s2 = s1+s2  //will not be interned 

For your first question no there is no differences since at compilation time the compiler can make a smart decision of replacing the variable by the content since const is hardcoded which make a better performance so you will not see any performance increase.

CodeCaster
  • 147,647
  • 23
  • 218
  • 272
BRAHIM Kamel
  • 13,492
  • 1
  • 36
  • 47