提问



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


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


string willi = string.Empty;


要么


string willi = String.Empty;


要么


string willi = "";


或者是什么?

最佳参考


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


其他答案表明每次使用""时都会创建一个新字符串。这不是真的 - 由于字符串实习,它将在每个程序集创建一次或每个AppDomain创建一次(或者可能在整个过程中创建一次 - 在前面不确定)。这种差异可以忽略不计 - 大量,大量无关紧要。


然而,您发现更具可读性是另一回事。它是主观的,因人而异 - 所以我建议你找出团队中大多数人喜欢的东西,并且为了保持一致性,所有人都这样做。我个人认为""更容易阅读。


""" "容易被彼此误认的论点并没有真正与我相提并论。除非你使用比例字体(我没有使用任何开发人员,这很容易分辨出来。

其它参考1


从性能和代码生成的角度来看,确实没有什么区别。在性能测试中,它们在哪一个更快与另一个之间来回,并且只有毫秒。


在查看幕后代码时,你真的没有看到任何区别。唯一的区别在于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 

其它参考2


最好的代码根本就没有代码:[83]



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



因此,更少的代码是更好的代码:首选""string.EmptyString.Empty。这两个六倍没有额外的好处 - 当然没有额外的清晰度,因为它们表达完全相同的信息。

其它参考3


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


请查看此链接以获取更多信息:
串空抗空引号[84]

其它参考4


我更喜欢stringString。选择string.Empty而不是""是选择一个并坚持它的问题。使用string.Empty的好处是它是你的意思非常明显,你不会在""中意外地复制"\x003"等不可打印的字符。

其它参考5


我不打算进入,但我看到一些错误的信息在这里被抛出。


我个人更喜欢string.Empty。这是个人偏好,我会根据个人情况与任何团队的意愿保持一致。


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


另外,这是一个鲜为人知的事实,使用是完全可以接受的。在其他环境中,的每个实例都将创建一个对象。但是,.NET会对其字符串进行实例化,因此将来的实例将从实习池中提取相同的不可变字符串,并且任何性能损失都可以忽略不计。资料来源:Brad Abrams。[85]

其它参考6


我个人更喜欢,除非有充分的理由去做更复杂的事情。

其它参考7


String.Emptystring.Empty是等价的。 String是BCL类名; string是它的C#别名(或快捷方式,如果你愿意的话)。与Int32int相同。有关更多示例,请参阅文档。[86]


""而言,我不太确定。


就个人而言,我总是使用string.Empty

其它参考8


几乎每个开发人员都会知道的意思。我个人第一次遇到String.Empty,不得不花一些时间搜索谷歌,弄清楚他们是否真的是完全相同的事情。

其它参考9


这个主题非常古老而且很长,所以如果在其他地方提到这种行为,请原谅。 (并指出我的答案)


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


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


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


在使用双引号进行初始化的情况下,您将获得预期的消息。


此链接的Connect文章中解释了此行为:https://connect.microsoft.com/VisualStudio/feedback/details/799810/c-warning-cs0219-not-reported-when-assign-non-constant-value [[[87]


基本上,如果我做对了,他们希望允许程序员使用函数的返回值设置变量以进行调试,而不会给他带来警告消息,因此他们仅在有明确的赋值和字符串的情况下限制警告。空不是常数而是场。

其它参考10


我在控制台应用程序中使用以下函数执行了这个非常简单的测试


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中称为 string interning 。 Eric Lippert在这里描述了一个非常好的博客。[88]

其它参考11


以上任何一种。


教导有许多更好的东西。比如什么颜色的树皮最适合树,我认为模糊的棕色与dulcet苔藓。

其它参考12


我没有什么区别。最后一个是最快的打字:)

其它参考13


我非常喜欢String.Empty,除了其他原因,以确保你知道它是什么,并且你没有意外删除内容,
但主要是为了国际化。
如果我在引号中看到一个字符串,那么我总是想知道这是否是新代码并且应该放入字符串表中。因此,每次代码更改/审核时,您需要查找引号中的内容,是的,您可以过滤掉空字符串,但我告诉人们,除非您知道它不会被本地化,否则永远不要将字符串放在引号中。

其它参考14


没有人提到在VisualStudio中字符串的颜色编码与字符串不同。这对可读性很重要。此外,小写通常用于变量和类型,但不是很大,但String.Empty是常量而不是var或类型。

其它参考15


stringSystem.String类型的同义词,它们是相同的。


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


我不会在代码中使用字符常量,而是string.EmptyString.Empty - 更容易看出程序员的意思。


stringString之间我更喜欢小写string,因为我曾经多次使用Delphi而且Delphi风格是小写的string


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

其它参考16


没关系 - 它们完全是一回事。
但是,主要的是你必须一致


附:我一直在为这种什么是正确的东西而斗争。

其它参考17


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

其它参考18


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


[[编辑]]


此外,您可能希望始终使用stringString来保持一致性,但那只是我。

其它参考19


它完全是一种代码风格的偏好,可以解决.NET如何处理字符串的问题。不过,这是我的意见:)


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


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


我很少使用未声明的字符串文字,因为我喜欢能够扫描代码以将它们组合成可重用的命名常量。编译器总是用文字替换常量,所以这更像是一种避免魔术字符串/数字的方法,并用名称给它们带来更多意义。另外,更改值更容易。

其它参考20


我赞成string.Empty而不是String.Empty因为你可以使用它而不需要在文件中包含using System;


至于选择""而不是string.Empty,这是个人偏好,应由您的团队决定。

其它参考21


从长远来看,编译器应该使它们完全相同。选择一个标准,以便您的代码易于阅读,并坚持使用它。

其它参考22


我只是看了一些代码,这个问题突然出现在我脑海中,我之前读过这个问题。这当然是一个可读性问题。


考虑以下C#代码......


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


VS


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


我个人认为后者不那么模糊,更容易阅读。


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

其它参考23


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


是的,这是一个非常多的判断调用,但是当一种语言为您提供多种方法时,我倾向于倾向于编译时监督最多且编译时强制最强的那种。那是不是。这完全是为了表达具体的意图。


如果键入string.EMpty或Strng.Empty,编译器会让您知道错误。立即。它根本不会编译。作为开发人员,您引用特定的意图,编译器(或其他开发人员)不能以任何方式误解,并且当您做错时,您不能创建错误。


如果您在表示时键入,反之亦然,编译器会愉快地执行您告诉它要执行的操作。另一位开发人员可能会或可能不会收集您的具体意图。 Bug已创建。


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


只要有可能,让编译器为您工作,并消除人为错误的可能性,无论多小。 IMO,正如其他人所引用的那样,它胜过可读性。


特殊性和编译时执行。这是晚餐的意思。

其它参考24


我使用因为它会在我的代码中以鲜明的黄色着色...由于某种原因,String.Empty在我的Visual Studio代码主题中都是白色的。而且我认为这对我最重要。

其它参考25


我认为第二个是正确的,但说实话,我认为它不重要。编译器应该足够聪明,可以将任何一个编译成完全相同的字节码。我自己使用。

其它参考26


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



  正如大卫所暗示的那样,String.Empty""之间的差异非常小,但存在差异。 ""实际上创建了一个对象,它可能会被拉出字符串实习池,但仍然...... String.Empty没有创建对象...所以如果你真的在寻找内存效率,我建议String.Empty。但是,你应该记住差异是如此微不足道,你将永远不会在你的代码中看到它...

  至于System.String.Emptystring.EmptyString.Empty ......我的护理水平很低;-)


其它参考27


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

其它参考28


虽然差异非常非常小,但差异仍然存在。


1)创建对象,而String.Empty则不创建对象。但是这个对象将被创建一次,如果代码中有另一个,将在稍后从字符串池中引用。


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