What is the difference between String.Empty and “” (empty string)?

后端 未结 17 1556
礼貌的吻别
礼貌的吻别 2020-11-22 03:25

In .NET, what is the difference between String.Empty and \"\", and are they interchangable, or is there some underlying reference or Localization i

相关标签:
17条回答
  • 2020-11-22 04:00

    String.Empty is a readonly field while "" is a const. This means you can't use String.Empty in a switch statement because it is not a constant.

    0 讨论(0)
  • 2020-11-22 04:00

    The above answers are technically correct, but what you may really want to use, for best code readability and least chance of an exception is String.IsNullOrEmpty(s)

    0 讨论(0)
  • 2020-11-22 04:00

    String.Empty does not create an object whereas "" does. The difference, as pointed out here, is trivial, however.

    0 讨论(0)
  • 2020-11-22 04:04

    Eric Lippert wrote (June 17, 2013):
    "The first algorithm I ever worked on in the C# compiler was the optimizer that handles string concatenations. Unfortunately I did not manage to port these optimizations to the Roslyn codebase before I left; hopefully someone will get to that!"

    Here are some Roslyn x64 results as of January 2019. Despite the consensus remarks of the other answers on this page, it does not appear to me that the current x64 JIT is treating all of these cases identically, when all is said and done.

    Note in particular, however, that only one of these examples actually ends up calling String.Concat, and I'm guessing that that's for obscure correctness reasons (as opposed to an optimization oversight). The other differences seem harder to explain.


    default(String)   +   { default(String),   "",   String.Empty }

    static String s00() => default(String) + default(String);
        mov  rax,[String::Empty]
        mov  rax,qword ptr [rax]
        add  rsp,28h
        ret
    
    static String s01() => default(String) + "";
        mov  rax,[String::Empty]
        mov  rax,qword ptr [rax]
        add  rsp,28h
        ret
    
    static String s02() => default(String) + String.Empty;
        mov  rax,[String::Empty]
        mov  rax,qword ptr [rax]
        mov  rdx,rax
        test rdx,rdx
        jne  _L
        mov  rdx,rax
    _L: mov  rax,rdx
        add  rsp,28h
        ret
    

    ""   +   { default(String),   "",   String.Empty }

    static String s03() => "" + default(String);
        mov  rax,[String::Empty]
        mov  rax,qword ptr [rax]
        add  rsp,28h
        ret
    
    static String s04() => "" + "";
        mov  rax,[String::Empty]
        mov  rax,qword ptr [rax]
        add  rsp,28h
        ret
    
    static String s05() => "" + String.Empty;
        mov  rax,[String::Empty]
        mov  rax,qword ptr [rax]
        mov  rdx,rax
        test rdx,rdx
        jne  _L
        mov  rdx,rax
    _L: mov  rax,rdx
        add  rsp,28h
        ret
    

    String.Empty   +   { default(String),   "",   String.Empty }

    static String s06() => String.Empty + default(String);
        mov  rax,[String::Empty]
        mov  rax,qword ptr [rax]
        mov  rdx,rax
        test rdx,rdx
        jne  _L
        mov  rdx,rax
    _L: mov  rax,rdx
        add  rsp,28h
        ret
    
    static String s07() => String.Empty + "";
        mov  rax,[String::Empty]
        mov  rax,qword ptr [rax]
        mov  rdx,rax
        test rdx,rdx
        jne  _L
        mov  rdx,rax
    _L: mov  rax,rdx
        add  rsp,28h
        ret
    
    static String s08() => String.Empty + String.Empty;
        mov  rcx,[String::Empty]
        mov  rcx,qword ptr [rcx]
        mov  qword ptr [rsp+20h],rcx
        mov  rcx,qword ptr [rsp+20h]
        mov  rdx,qword ptr [rsp+20h]
        call F330CF60                 ; <-- String.Concat
        nop
        add  rsp,28h
        ret
    


    Test details

    Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
    AMD64 Release
    [MethodImpl(MethodImplOptions.NoInlining)]
    'SuppressJitOptimization' = false
    
    0 讨论(0)
  • 2020-11-22 04:06

    The previous answers were correct for .NET 1.1 (look at the date of the post they linked: 2003). As of .NET 2.0 and later, there is essentially no difference. The JIT will end up referencing the same object on the heap anyhow.

    According to the C# specification, section 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx

    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 (Section 7.9.7) appear in the same assembly, these string literals refer to the same string instance.

    Someone even mentions this in the comments of Brad Abram's post

    In summary, the practical result of "" vs. String.Empty is nil. The JIT will figure it out in the end.

    I have found, personally, that the JIT is way smarter than me and so I try not to get too clever with micro-compiler optimizations like that. The JIT will unfold for() loops, remove redundant code, inline methods, etc better and at more appropriate times than either I or the C# compiler could ever anticipate before hand. Let the JIT do its job :)

    0 讨论(0)
  • 2020-11-22 04:07

    what is the difference between String.Empty and "", and are they interchangable

    string.Empty is a read-only field whereas "" is a compile time constant. Places where they behave differently are:

    Default Parameter value in C# 4.0 or higher

    void SomeMethod(int ID, string value = string.Empty)
    // Error: Default parameter value for 'value' must be a compile-time constant
    {
        //... implementation
    }
    

    Case expression in switch statement

    string str = "";
    switch(str)
    {
        case string.Empty: // Error: A constant value is expected. 
            break;
    
        case "":
            break;
    
    }
    

    Attribute arguments

    [Example(String.Empty)]
    // Error: An attribute argument must be a constant expression, typeof expression 
    //        or array creation expression of an attribute parameter type
    
    0 讨论(0)
提交回复
热议问题