在C#中,我应该使用string.Empty还是String.Empty或“”来初始化字符串?


704

在C#中,我想用一个空字符串初始化一个字符串值。

我应该怎么做?正确的方法是什么,为什么?

string willi = string.Empty;

要么

string willi = String.Empty;

要么

string willi = "";

要不然是啥?


6
另请参见Java的类似讨论:stackoverflow.com/questions/213985/…–
harpo,

38
当然,最好使用String.IsNullOrEmpty(string myString)?
ZombieSheep 2009年

3
我使用[string.IsNullOrWhiteSpace(stringvalue)] ...在.Net 4.0中有效。要初始化,我只需使用:[var text =“”;]简单,易读,并且花费最少的时间键入:)
Jalal El-Shaer

60
更重要的是变量的搞笑名称。
2011年

5
使我感兴趣的是为什么甚至还有一个Empty属性。一切都很好,但不是必需的和完整的必须。
2012年

Answers:


806

使用您和您的团队最容易阅读的内容。

其他答案表明,每次使用时都会创建一个新字符串""。这是不正确的-由于字符串内部操作,它会针对每个程序集创建一次,也可能针对每个AppDomain创建一次(或者可能对整个过程创建一次-不确定在那方面)。这种差异可以忽略不计-在很大程度上,在很大程度上是微不足道的。

但是,您发现更具可读性的是另一回事。它是主观的,并且因人而异-因此,我建议您了解团队中大多数人的喜好,并且所有人都希望保持一致。我个人觉得""更容易阅读。

""" "容易被彼此误解的论点并没有真正被我接受。除非您使用比例字体(并且我没有与任何使用过这种字体的开发人员合作),否则很容易分辨出区别。


75
当您期望看到“”时,您的眼睛会欺骗您,您很容易将“”误认为是“”。这就是为什么编辑别人写的东西更容易的原因。您的大脑没有关于文本的先入为主的想法,因此更容易找出异常。
tvanfosson

125
@tvanfosson:那么,您(或同事)是否真的被此漏洞所咬而作为错误?我怀疑这种说法,但实际上并未引起任何问题。我已经使用“”多年了,却从未出错...
Jon Skeet

34
就我个人而言,我一直使用String.Empty,每当我想对字符串使用静态方法时,都使用大写的'S',这只是个人喜好,使我能够将类型与变量区分开。但这只是从java在commons.lang中使用StringUtils.EMPTY产生的结果。感兴趣的一点是我几乎是盲人,这无疑对我的可读性有所帮助。
Brett Ryan

79
您给了我灵感,可以开始在Times New Roman中进行开发。
贾斯汀·罗斯巴奇

73
由于某些模糊的原因,string.Empty它不是常数。这意味着在许多情况下需要编译时常量,string.Empty甚至是不合法的。这包括语句中的case ""switch可选参数的默认值,应用属性时的参数和属性以及许多其他情况(留给读者阅读)。因此,鉴于string.Empty在某些常见情况下不允许这样做,最好使用""-everywhere约定。
Jeppe Stig Nielsen,

375

从性能和代码生成的角度来看,确实没有什么区别。在性能测试中,它们之间来回切换得更快,只有几毫秒。

在查看幕后代码时,您实际上也看不到任何区别。唯一的区别在于IL,它们string.Empty使用操作码ldsfld""使用操作码ldstr,但这仅是因为它string.Empty是静态的,并且两条指令执行相同的操作。如果查看所生产的装配,则完全相同。

C#代码

private void Test1()
{
    string test1 = string.Empty;    
    string test11 = test1;
}

private void Test2()
{
    string test2 = "";    
    string test22 = test2;
}

IL代码

.method private hidebysig instance void 
          Test1() cil managed
{
  // Code size       10 (0xa)
  .maxstack  1
  .locals init ([0] string test1,
                [1] string test11)
  IL_0000:  nop
  IL_0001:  ldsfld     string [mscorlib]System.String::Empty
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  stloc.1
  IL_0009:  ret
} // end of method Form1::Test1
.method private hidebysig instance void 
        Test2() cil managed
{
  // Code size       10 (0xa)
  .maxstack  1
  .locals init ([0] string test2,
                [1] string test22)
  IL_0000:  nop
  IL_0001:  ldstr      ""
  IL_0006:  stloc.0
  IL_0007:  ldloc.0
  IL_0008:  stloc.1
  IL_0009:  ret
} // end of method Form1::Test2

汇编代码

        string test1 = string.Empty;
0000003a  mov         eax,dword ptr ds:[022A102Ch] 
0000003f  mov         dword ptr [ebp-40h],eax 

        string test11 = test1;
00000042  mov         eax,dword ptr [ebp-40h] 
00000045  mov         dword ptr [ebp-44h],eax 
        string test2 = "";
0000003a  mov         eax,dword ptr ds:[022A202Ch] 
00000040  mov         dword ptr [ebp-40h],eax 

        string test22 = test2;
00000043  mov         eax,dword ptr [ebp-40h] 
00000046  mov         dword ptr [ebp-44h],eax 

13
@PrateekSaluja:要查看IL,可以使用Visual Studio附带的ildasm.exe。要查看分解,请在遇到断点时使用调试菜单上的“反汇编”窗口(也可以在发布代码中使用)。
Thomas Bratt 2012年

1
讨厌我要推荐此产品。.但是,.Reflector可以让您在拆卸信号源时选择语言,并且IL是一个选择!ILDASM只是过时的感觉... MS工具团队似乎没有完善或发布好的工具!
felickz 2012年

80

最好的代码是根本没有代码

编码的基本本质是,作为程序员,我们的任务是认识到我们做出的每个决定都是一个权衡。[…] 简洁起见。根据测试要求增加其他尺寸。

因此,更少的代码是更好的代码:不想""string.EmptyString.Empty。这两者的长度是原来的六倍,并且没有额外的好处-当然也没有增加的清晰度,因为它们表示的是完全相同的信息。


1
但是在C#中,我们只能说string.IsNullOrWhitespace(s):p
felickz 2012年

31
我同意代码应尽可能小,但通常不会认为字符越少总是更好的代码。例如,当涉及变量命名时,与仅使用i和j相比,合理数量的字符通常会产生更好的名称。
Markus Meyer

3
@Markus这在很大程度上取决于:用于表示索引的循环变量,i 不是一个长变量名更好。更通用的,以相同的清晰度传达相同信息的较短的变量名总是可取的。只是为了表达必要的信息,您需要一定的字符长度,我并不否认这一点(没人可以)。
Konrad Rudolph

2
@Konrad:仅当循环很小且不包含任何其他索引时,i才是很好的变量名。但是我同意。可以更简短地说明传达相同的信息,这将是可取的,例如在string.Empty /“”情况下。string.Empty不会增加任何清晰度。
Markus Meyer

对我来说:string.Empty表示此字符串在任何时候都应该为空,而“”表示在编写此字符串时可以为空,但是您可以随意更改。
aeroson

54

一个区别是,如果使用switch-case语法,则不能编写,case string.Empty:因为它不是常量。你得到一个Compilation error : A constant value is expected

请查看此链接以获取更多信息: string-empty-versus-empty-quotes


22
switch声明是一个很好的例子。另外,如果您设置了可选参数(例如)void MyMethod(string optional = "") { ... },则也无法使用string.Empty。然后,当然,如果要定义const字段或局部变量,const string myString = "";则再次""是唯一的选择。如果只是string.Empty一个恒定的字段,就不会有任何区别。但这不是,因此在某些情况下,您必须使用""。那么为什么不一直使用""呢?
杰普·斯蒂格·尼尔森

5
这是一个非常有力的论据,因为使用会string.Empty阻止您在代码库中实现一致性:您必须使用两个不同的实体来表示同一件事。要添加到您不能做的事情清单中:不能string.Emptyattribute一起使用。
Pragmateek

2
很好点!链接断开。这是内容的副本:web.archive.org/web/20131230161806/http
//kossovsky.net/…– ygoe 2015年

42

我宁愿stringString。选择string.Empty""是选择一个,并与它坚持的问题。使用的好处string.Empty是您的意思很明显,而且您不会意外地复制不可复制的字符(例如"\x003"""


101
我认为,如果您不小心将不可打印的字符复制到代码中,则会遇到比此问题更大的问题;)
Jon Skeet

9
ASCII \ 003恰好是我使用过的B2B消息的字段定界符:)
Jimmy

7
(我还建议避免\ x转义,顺便说一句-很难发现结果完全不同的“ \ x9Bad Compiler”和“ \ x9Good Compiler”之间的区别!)
Jon Skeet

就个人而言,每当在String上调用静态方法时,我都更喜欢String而不是string。但是我几乎是盲目的,这是我个人不喜欢的个人偏好。
Brett Ryan

2
@Jimmy当然,但是我们正在谈论空字符串。""我声称,复制/粘贴为空时很危险的参数,因为您永远不会复制/粘贴空字符串。对于其他字符串,当然总是要注意这一点。
Timo 2015年

22

我本来不会插话,但是我看到一些错误的信息被扔到这里。

我个人更喜欢string.Empty。这是个人喜好,我会根据具体情况选择与我合作的任何团队。

正如其他人提到的,string.Empty和之间没有任何区别String.Empty

另外,这是一个鲜为人知的事实,使用“”是完全可以接受的。在其他环境中,“”的每个实例都将创建一个对象。但是,.NET会保留其字符串,因此将来的实例将从内部存储池中提取相同的不可变字符串,并且任何性能损失都可以忽略不计。资料来源:布拉德·艾布拉姆斯(Brad Abrams)


20
我不明白为什么“技术上”每个“”实例都会创建一个对象。字符串被嵌入的不只是机会-在C#规范中。
乔恩·斯基特

15

我个人更喜欢“”,除非有充分理由要更复杂一些。


13

String.Emptystring.Empty等价。String是BCL类别名称;string是它的C#别名(如果需要的话,也可以是快捷方式)。与Int32和相同int。有关更多示例,请参阅文档

""我而言,我不确定。

我个人总是使用string.Empty


10

几乎每个开发人员都会知道“”的含义。我个人第一次遇到String.Empty,不得不花一些时间在Google上搜索以确定它们是否确实同一回事。


3
这是一个公共的只读字符串字段,其值为“” ...为什么会更改?
Matthew Whited

5
您错过了@Jason提出的要点。您怎么知道第一次看到的是string.Empty什么?您知道""第一次看到它是什么吗?
David R Tribble

10

这个话题很老很长,如果在其他地方提到过这种行为,请原谅。(并指出涵盖该问题的答案)

如果使用string.Empty双引号,我发现编译器的行为有所不同。如果您不使用以string.Empty或双引号初始化的字符串变量,则差异将显示出来。

如果使用进行初始化,string.Empty则编译器警告

CS0219 - The variable 'x' is assigned but its value is never used

不会发出,而在使用双引号进行初始化的情况下,您会得到预期的消息。

在此链接的“连接”文章中对此行为进行了说明:https : //connect.microsoft.com/VisualStudio/feedback/details/799810/c-warning-cs0219-not-reported-when-assign-non-constant-value

基本上,如果我做对了,他们希望允许程序员设置具有函数返回值的变量用于调试目的,而不会在警告消息中打扰他,因此,他们仅在使用昂贵的分配和字符串的情况下才限制警告。空不是常数而是字段。


1
我相信您是第一个提到的人。几个月前,我已经阅读了该问答,并且不记得这种区别,如果提到的话,我会记得。
Palec '16

2
有趣。注意,声明var unused = "literal";可以由编译器完全优化(删除)。它没有副作用。另一方面,var unused = MyClass.Member;不能完全删除。那是因为阅读Member可能会有副作用。如果Member是具有访问器的静态属性get,则很明显必须保留对getter的调用。但是,即使Member是静态字段,也可能会产生静态构造函数可能运行的副作用。肯定会有这种方式是不好的编码风格。但是你需要一个假人来阅读Member
杰普·斯蒂格·尼尔森

9

我在控制台应用程序中使用以下方法执行了此非常简单的测试:

private static void CompareStringConstants()
{
    string str1 = "";
    string str2 = string.Empty;
    string str3 = String.Empty;
    Console.WriteLine(object.ReferenceEquals(str1, str2)); //prints True
    Console.WriteLine(object.ReferenceEquals(str2, str3)); //prints True
}

这清楚地表明,所有三个变量,即str1str2str3虽然使用不同的语法被初始化都指向完全相同的字符串中存储对象(零长度的)。我在.NET 4.5控制台应用程序中执行了此测试。因此,在内部,它们没有什么区别,所有这些都归结为您要用作程序员的便利性。字符串类的这种行为在.NET中称为字符串实习。埃里克·利珀特(Eric Lippert)在这里有一个非常不错的博客描述了这个概念。


8

以上任何一项。

有很多很多更好的东西值得赞美。例如什么颜色的树皮最适合一棵树,我认为模糊的棕色和淡淡的青绿色。


7

除了其他原因之外,我强烈建议使用String.Empty,以确保您知道它是什么,并且您没有意外删除内容,但主要是为了国际化。如果我在引号中看到一个字符串,那么我总是不得不怀疑这是否是新代码,应该将其放入字符串表中。因此,每次代码更改/查看时,您都需要查找“引号中的内容”,是的,您可以过滤出空字符串,但是我告诉人们,除非您知道不会将字符串本地化,否则最好不要在引号中添加字符串。



6

stringSystem.Stringtype的同义词,它们是相同的。

值也相同: string.Empty == String.Empty == ""

我不会用字符常量“”中的代码,而string.EmptyString.Empty-更容易看到什么意思程序员。

string和之间,Stringstring更喜欢小写字母,只是因为我曾经在Delphi工作多年,而Delphi风格却是小写字母string

所以,如果我是你的老板,你会写 string.Empty


6

我宁愿这样做string.EmptyString.Empty因为您可以使用它而无需using System;在文件中包含a 。

至于采摘""string.Empty,这是个人喜好,应该由你的团队来决定。


2
我是团队的唯一成员,我该如何决定?扔骰子?
Gqqnbig

1
对于那些可能想知道如何在string.Empty不导入using System名称空间的情况下使用常量的人来说,C#中的关键字只是简单地转换为包含名称空间的完全限定名称,然后在输出* .dll或*中将其作为MSIL编写。 exe文件。string.Empty就像System.String.Empty编译器在MSIL中一样有效地被编写。而且,您可能已经知道,如果提到完全限定的类型名称,则可以跳过在代码文件顶部导入名称空间的步骤。
RBT

5

我没有改变。最后一个虽然是打字最快的:)


4

没关系-它们是完全一样的东西。但是,最主要的是您必须保持一致

ps我一直都在为这种“什么是正确的事情”而苦恼。


1
在现代世界中,“一致”表示全世界所有团队之间的一致,这是StackOverflow的目标之一。如果我建议的话,让我们使用String.Empty。
帕维尔·拉兹维洛夫斯基

1
某些语言没有Empty常量,我可以想到的所有语言都允许零长度字符串“”。因此,我投票赞成与其他语言保持一致。:)
TomXP411 2014年

4

这完全是一种代码风格的偏爱,它是.NET如何处理字符串的方式。但是,这是我的意见:)

访问静态方法,属性和字段时,我总是使用BCL类型名称:String.EmptyInt32.TryParse(...)Double.Epsilon

在声明新实例时,我总是使用C#关键字:int i = 0;string foo = "bar";

我很少使用未声明的字符串文字,因为我希望能够扫描代码以将它们组合为可重用的命名常量。编译器无论如何都用文字替换常量,因此这是避免魔术字符串/数字并使用名称赋予它们更多含义的一种方式。另外,更改值更容易。


3

我使用第三个,但在其他两个中,第一个似乎不太奇怪。string是String的别名,但是在分配中看到它们会感到不舒服。


3

前两个中的任何一个对我来说都是可以接受的。我将避免使用最后一个,因为通过在引号之间放置一个空格来引入bug相对容易。通过观察很难找到这个特定的错误。假设没有错别字,所有这些在语义上都是等效的。

[编辑]

另外,您可能希望始终使用stringString来保持一致性,但这仅是我自己。


我同意这一说法,但是当我懒惰时,我仍然过着危险的生活。无论如何,我认为我没有机会编写使用字符串的代码,然后再将其分配给变量声明之外。实际上,尽管有风险,我还是必须初始化字符串,这对我来说很烦。
EnocNRoll-AnandaGopal Pardue,2009年

3

我亲眼目睹了“”两次导致(次要)问题。一次是由于一个基于团队编程的初级开发人员的错误,另一个是简单的错字,但事实是使用字符串。Empty可以避免这两个问题。

是的,这在很大程度上是一种判断,但是当一种语言为您提供多种处理方式时,我倾向于倾向于编译器监督最多,编译时间执行最强的一种。那不是 “”。这都是关于表达特定意图的。

如果键入string.EMpty或Strng.Empty,编译器会告诉您您做错了。立即。它根本无法编译。作为开发人员,您要指出特定的意图,即编译器(或其他开发人员)不能以任何方式曲解,并且如果您做错了,就不能创建错误。

如果您在输入“”时键入“”,反之亦然,那么编译器会很乐意地执行您告诉它的操作。另一个开发人员可能会也可能无法收集您的特定意图。错误创建。

在string.Empty之前很久,我已经使用了定义EMPTY_STRING常量的标准库。我们仍然在case语句中使用该常量,其中不允许使用string.Empty。

尽可能使编译器为您工作,并消除人为错误的可能性,无论大小如何。IMO,这胜过其他人所引用的“可读性”。

特殊性和编译时间执行。晚餐是吃什么。


3

我使用“”是因为它在我的代码中会明显地染成黄色...由于某种原因,String.Empty在我的Visual Studio Code主题中全为白色。我认为这对我来说最重要。



2

我只是在看一些代码,这个问题浮现在脑海,我已经读了一段时间。这当然是可读性的问题。

考虑下面的C#代码...

(customer == null) ? "" : customer.Name

(customer == null) ? string.empty : customer.Name

我个人认为后者不太明确,更易于阅读。

正如其他人指出的,实际差异可以忽略不计。


1

我认为第二个是“适当的”,但是老实说,我认为这并不重要。编译器应该足够聪明,可以将任何一个编译为完全相同的字节码。我自己使用“”。


1

尽管差异非常大,但差异仍然存在。

1)“”创建对象,而String.Empty不创建对象。但是,此对象将创建一次,并且如果代码中还有另一个“”,则稍后将在字符串池中对其进行引用。

2)字符串和字符串相同,但是我建议使用String.Empty(以及String.Format,String.Copy等),因为点表示法表示类,而不是运算符,并且以大写字母开头的类符合C#编码标准。


1
string.Empty “”,请检查源代码
dss539,2009年

1

http://blogs.msdn.com/b/brada/archive/2003/04/22/49997.aspx上

正如David所暗示的,String.Empty和之间的差异""很小,但是存在差异。""实际上创建了一个对象,它很可能会从字符串实习生池中拉出,但仍然...虽然String.Empty没有创建任何对象...所以我建议,如果您真的在寻找最终的内存效率String.Empty。但是,请记住,差异是如此琐碎,以至于您永远都不会在代码中看到它……
至于System.String.Emptystring.EmptyString.Empty……我的护理水平很低;-)


1
那条MSDN博客文章是在2003年...。您确定这对于最新的.NET版本仍然适用吗?
卡斯滕·舒特

@CarstenSchütte:在我看来,这样的功能并没有太大的改变……如果确实如此,那么互联网上对此就有些嗡嗡声。
sergiol 2013年

3
@sergiol如果字段比文字字段更有效,那么这无疑是一个性能错误。因此,希望它现在可以解决。
Konrad Rudolph

1

空字符串就像空集一样,只是每个人都用来调用的名称""。同样在正式语言中,由长度为零的字母创建的字符串称为空字符串。set和string都有一个特殊的符号。空字符串:ε和空集:∅。如果您想谈论这个零长度的字符串,则将其称为空字符串,这样每个人都可以确切地知道您指的是什么。现在,如果您将其命名为空字符串,为什么不在string.Empty代码中使用它,则表明其意图是明确的。缺点是它不是常量,因此并非在所有地方都可用,例如属性。(由于某些技术原因,它不是常数,请参阅参考资料。)


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.