关于.NET:String.empty和””(empty string)有什么区别?

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

在.NET中,String.Empty""之间的区别是什么,它们是可交换的,还是围绕String.Empty将确保的平等性存在一些潜在的参考或本地化问题?


(P)In Net prior to version 2.0,EDOCX1 plus 0 commerciates an object while EDOCX1 pental 1 commerciales no objectref,which makes EDOCX1 individual 1 more efficient.(p)(P)In version 2.0 and later of Net,all occurrences of EDOCX1 commercial 0 refer to the same string逐字记录,which means EDOCX1 biblic 0 is equivalent to EDOCX1 original 5,but still not as fast as EDOCX1.(p)(P)EDOCX1 6是最快的选项,但EDOCX1是5个音标的音标为Slightly Cleaner Code。(p)(P)See the Net specification for more information.(p)


布尔奇1(P)EDOCX1是一个读地,只有爱多克X1是一个温馨的时代君士坦特。Places where they behave differently are:(p)(P)Default parameter value in C§35;4.0 or higher(p)字母名称(P)Case expression in switch statement(p)字母名称(P)Attribute Arguments(p)字母名称


(P)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 reference the same object on the hep anyhow.(p)(P)According to the C§35;Specification,Section 2.4.4.5:http://msdn.microsoft.com/en-us/library/aa691090(VS.71)。(p)布尔奇1(P)Someone even mentions this in the comments of Brad Abram's Post(p)(P)In summary,the practical result of"vs.string.empty is nil.The jit will figure it out in the end.(p)(P)I have found,personally,that the jit is way smarter than me and so I try not to get too clever with micro-compiler优化like that.The jit will unfortold for(……)loops,remove冗余code,inline methods,etc better and at more appropriate times than either i or the C′35;compiler could every anticite before hand.Let the jit do its job:(p)


(P)字母名称:EDOCX1是一个读字段这意味着你不能在一个Switch声明中使用EDOCX1,因为它不是一个标准。(p)


(P)Another difference is that string.Empty generatives larger cil code.While the Code for Reference"and String.Empty is the same length,the compiler doesn't optimize string concateration(see Eric Lippert's博客post)for string.Empty arguments.The following equivalent functions(p)字母名称(P)这一代(p)字母名称


(P)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.isnulorampty(s)(p)


使用String.Empty而不是""

This is more for speed than memory usage but it is a useful tip. The
"" is a literal so will act as a literal: on the first use it is
created and for the following uses its reference is returned. Only one
instance of "" will be stored in memory no matter how many times we
use it! I don't see any memory penalties here. The problem is that
each time the "" is used, a comparing loop is executed to check if the
"" is already in the intern pool. On the other side, String.Empty
is a reference to a "" stored in the .NET Framework memory zone.
String.Empty is pointing to same memory address for VB.NET and C#
applications. So why search for a reference each time you need ""
when you have that reference in String.Empty?

参考文献:String.Empty""的比较


(P)String.Empty does not create an object where"does.The difference,as pointed out here,is little,however.(p)


(P)I tend to use EDOCX1 penographic 1 commercial rather than EDOCX1 commercial 0 for one simple,yet not obvious reason:EDOCX1 20 original and EDOCX1 original 0 is not the same,the first one actually has 16 zero width characters in it.Obviously no competent developer is going to put and zero width characters in to their code,but if they do get in there,it can be a maintenance nightmare.(p)(P)注:(p)

  • (P)我用的就是这个例子。(p)
  • (P)Not sure if so is going to eat those characters,but try it yourself with one of the many Zero-width characters(p)
  • (P)I only came upon this thanks to https://codegolf.stackxchange.com/(p)


(P)All instances of"are the same,interned string逐字逐句(or they should be).So you really won't be throwing a new object on the hep every time you use"but just creating a reference to the same,interned object.他说,我喜欢脱衣舞。I think it makes it code more ready.(p)


(P)它只是没有问题!(p)(P)Some past discussion of this:(p)(P)http://www.codinghor.com/blog/archives/000185.html(p)(P)http://blogs.msdn.com/brada/archive/2003/04/22/49997.aspx(p)(P)http://blogs.msdn.com/brada/archive/2003/04/27/50014.aspx(p)


字母名称(P)EDOCX1 14-Pshes a new object reference to a string逐字记录stored in the metata.(p)字母名称(P)EDOCX1音标15音标一站现场的价值与评价斯塔克(p)(P)I tend to use EDOCX1 theocx1 pental 1 communal instead of EDOCX1 commercial 0 because IMHO's clearer and less vb-ish.(p)


从实体框架的角度来看:EF版本6.1.3在验证时似乎处理string.empty和"不同"。

出于验证目的,空被视为空值,如果在必需(属性化)字段上使用,则会引发验证错误;其中a s"将通过验证,而不是引发错误。

这个问题可以在EF7+中解决。参考文献:-https://github.com/aspnet/entityframework/issues/2610)。

编辑:【必选(allowEmptyStrings=true)】将解决此问题,允许string.empty进行验证。


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

以下是截至2019年1月的一些Roslyn X64结果。尽管本页上其他答案的一致意见,但在我看来,当前的X64 JIT处理所有这些情况的方式并不完全相同,因为所有这些都是说出来做出来的。

但是,请特别注意,实际上只有一个示例最终调用了String.Concat,我猜测这是出于模糊的正确性原因(而不是优化监督)。其他的差异似乎难以解释。

默认(字符串)+…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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

"+…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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+…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
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

测试细节

1
2
3
4
Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false

由于string.empty不是编译时常量,因此不能将其用作函数定义中的默认值。

1
2
3
4
public void test(int i=0,string s="")
    {
      // Function Body
    }


这里的每个人都作了一些很好的理论澄清。我也有类似的怀疑。所以我尝试了一个基本的编码。我发现了不同。这就是区别。

1
2
3
4
5
6
string str=null;
Console.WriteLine(str.Length);  // Exception(NullRefernceException) for pointing to null reference.


string str = string.Empty;
Console.WriteLine(str.Length);  // 0

因此,"空"似乎意味着绝对无效的字符串。空意味着它包含某种值,但它是空的。