Is there any performance increase by changing this .NET string to a const? Does the IL automatically do that?

前端 未结 4 1143
深忆病人
深忆病人 2021-01-24 13:07

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

if (extension.Eq         


        
相关标签:
4条回答
  • 2021-01-24 13:35

    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".

    0 讨论(0)
  • 2021-01-24 13:50

    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.

    0 讨论(0)
  • 2021-01-24 13:53

    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.

    0 讨论(0)
  • 2021-01-24 13:56

    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.

    0 讨论(0)
提交回复
热议问题