string.Empty属性的意义是什么


35

为什么将该物业string foo = string.Empty列入BCL?似乎比仅使用空字符串(string foo = "")更冗长,更清晰


6
Nitpick:它不是语言的一部分。它是BCL的一部分。VB.NET和F#以及其他所有.NET语言都可以使用它。
奥德

19
因为否则,您将无法做类似的typeof(string).GetField("Empty").SetValue(null, " ");
Mason Wheeler 2012年

1
@MasonWheeler-反思的乐趣。为了真正的邪恶,您需要自省,是吗?
Oded 2012年

1
@ MasonWheeler,+ 1。哦,天哪,护目镜,他们什么也没做!]
Machado 2012年

1
@MasonWheeler那是纯净的蒸馏邪恶。我喜欢这个。问您是否有兴趣:将其编写为不是更安全(并且性能也不错)public static string Empty { get { return string.Intern(""); } }
Jesse C. Slicer 2012年

Answers:


55

我只能在这里假设:

string.Empty为明确起见已定义-在初始化字符串时,从上下文中可能并不清楚""确实确实是初始化程序(而不是在测试过程中null" "或仅充当占位符)的上下文。使用string.Empty是对这种难题的肯定答案。

这也可能是对C的抛弃-C中的空字符串不是空字符串。它是一个字符数组,其第一个字符为null(因此为空),与C#不同。我的意思是,在不同的语言中,您将以不同的方式表示一个空字符串(并且它们可能具有不同的含义)- string.Empty避免了此类歧义。

与其他人对多个对象的说法相反,这不是问题,因为任何字符串文字都会在编译时被保留。这包括价值string.Empty- ""。任何时候只要在代码中重复上述任何一个,就会从内部池中检索该对象。每个应用程序域都是如此。


5
+1是迄今为止唯一的正确答案。
psr 2012年

有些语言甚至可能不会一个空字符串文字。显然,标准的Pascal没有。
dan04 '01

2
“ C中的空字符串不是空字符串” —但是,如果您编写"",您会得到{'\0'},因此空字符串文字和其他定义它的回旋方式之间没有区别。
2012年

14

我不确定自己从哪里学到的资源,但是使用它的一些要点包括:

  • .NET程序集中的每个字符串都是唯一的,因此具有

    string foo = "";
    string bar = "";
    

    由于字符串是不可变的,因此在输出程序集中产生2个字符串。具有两个参考string.Empty可以减小组件的尺寸。

  • 明确的。当您发现string.Empty意图时,很明显它应该是一个空字符串。但是,如果遇到foo = ""这种情况,程序员是否在测试时删除了字符串的内容,却忘记了将其添加回去,还是应该这样呢?

1
将两个相同的字符串保留在内存中似乎是一种奇怪的行为。事实就是这样吗?
钻机2012年

36
实际上,情况恰好相反-这称为字符串实习(更确切地说是文字实习)。我肯定知道它是在Java和Python中完成的,而且我很确定在.NET语言中也是如此。当然,它只能在单个转换单元的范围内发生,因此,除非动态加载程序将这些数据统一起来,否则每个程序文件可能最终只有一个空字符串。仍然不是很多。

9
@delnan绝对正确。""/ string.Empty被拘禁,并且只会创建一个对象。
Oded 2012年

11
@Andy-所有字符串文字都在.NET中进行嵌入。并非所有字符串。默认情况下,以编程方式创建的字符串不会被拘禁。请参阅MSDN上的String.Intern
奥德

3
@Oded等:实际上,你们当中没有一个是完全正确的。首先,将文字插入程序集内,但不一定跨程序集。其次,是否在整个程序集之间插入空字符串是一个实现细节。有些版本的CLR使用,有些则没有。在其他答案之一中,有一篇指向我的文章的链接。看到它的细节。
埃里克·利珀特

2

不会为创建对象string.Empty。使用""将创建一个对象,该对象很可能来自字符串实习生池。

过去,人们已经进行过测试,并且String.Empty发布速度稍快,但这是微观优化。

String.Empty是这样的:

//The Empty constant holds the empty string value.   
//We need to call the String constructor so that the compiler doesn't mark 
//this as a literal.   
//Marking this as a literal would mean that it doesn't show up as a field 
//which we can access from native.  
public static readonly String Empty = ""; 

2
所以你的意思是...?

1
关键是String.Empty基本上是“”的常量。查找String.cs的作者以获取更深层的含义。:)
乔恩·雷诺

0

这是优化内存消耗和优化字符串比较的问题。每次在应用程序中使用空字符串时,都将分配一个包含0个字符的字符串对象。至于字符串比较,可以通过比较引用(指针)而不是逐个字符来完成,即使对于空字符串,这也更快。

如果您在应用程序中多次使用相同的字符串,则可以通过对字符串调用String.Intern()来使用相同的机制。但是,如果每个字符串仅使用一次,则只会使用更多的内存。

因此,String.Empty只是对大多数.Net应用程序值得进行的特殊情况的优化,这就是将其集成到BCL中的原因。

有关此主题的更多详细信息,我强烈建议阅读Eric Lippert的博客文章

您还应该查看他的博客文章引用的此文档


4
仅链接答案不能给出好的答案。如果埃里克(Eric)重组了博客,那么这个答案将毫无用处。请在此处汇总帖子,以便我们掌握所有信息。
克里斯·弗雷德

7
@ChrisF:我永远都无法重组博客。那将是一个巨大的变化,您知道我对此有何看法。
埃里克·利珀特

1
@EricLippert-我意识到您永远不会那样做,但是,仅链接答案不是一个好的答案,我们需要鼓励人们意识到这一点。
克里斯·夫(CheF)

3
@EricLippert不只是短暂的链接。这也与读者的礼貌有关,答案中至少应直接包含足够的内容,以便读者可以就是否应遵循链接提出意见。而且,即使在SE的脱机副本中,答案也应该有意义。
吉尔(Gilles)“所以,别再邪恶了”
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.