756

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

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

string willi = string.Empty;

或者

string willi = String.Empty;

或者

string willi = "";

要不然是啥?

4

30 回答 30

856

使用您和您的团队认为最易读的任何内容。

其他答案建议每次使用时都会创建一个新字符串""。这不是真的 - 由于字符串实习,它将在每个程序集或每个 AppDomain 中创建一次(或者可能在整个过程中创建一次 - 在这方面不确定)。这种差异可以忽略不计 - 非常大,非常微不足道

但是,您发现哪个更具可读性是另一回事。这是主观的,并且会因人而异——所以我建议你找出团队中大多数人喜欢的东西,然后为了保持一致。我个人觉得""更容易阅读。

很容易被误认为彼此的论点""并没有真正与我相提并论。" "除非您使用的是比例字体(而且我没有与任何这样做的开发人员合作过),否则很容易区分。

于 2008-11-04T20:07:39.567 回答
386

从性能和代码生成的角度来看,确实没有区别。在性能测试中,他们在哪一个比另一个更快之间来回切换,而且只有几毫秒。

在查看幕后代码时,您也真的看不出任何区别。唯一的区别在于 IL,它string.Empty使用 opcodeldsfld""使用 opcode 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 
于 2009-10-19T13:31:16.547 回答
88

最好的代码是完全没有代码

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

因此,更少的代码就是更好的代码:""首选string.Emptyor String.Empty。这两个时间长了六倍,没有额外的好处——当然也没有增加清晰度,因为它们表达了完全相同的信息。

于 2008-11-04T20:04:34.440 回答
56

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

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

于 2011-08-26T08:58:10.727 回答
46

我宁愿string. String选择是选择一个并坚持下去的问题string.Empty""使用的好处string.Empty是你的意思很明显,而且你不会意外复制不可打印的字符,比如"\x003".""

于 2008-11-04T19:52:38.380 回答
24

我不打算插话,但我看到一些错误的信息被扔在这里。

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

string.Empty正如其他一些人所提到的,和之间根本没有区别String.Empty

此外,这是一个鲜为人知的事实,使用 "" 是完全可以接受的。在其他环境中,每个 "" 实例都会创建一个对象。但是,.NET 实习其字符串,因此未来的实例将从实习池中提取相同的不可变字符串,任何性能影响都可以忽略不计。资料来源:布拉德艾布拉姆斯

于 2008-11-04T20:07:08.307 回答
16

我个人更喜欢“”,除非有充分的理由来处理更复杂的事情。

于 2008-11-04T19:50:51.787 回答
14

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

""目前而言,我不太确定。

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

于 2008-11-04T19:53:07.430 回答
13

我在 .NET v4.5 控制台应用程序中使用以下方法执行了一个简单的测试:

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
}

这表明所有三个变量str1,尽管使用不同的语法进行初始化str2str3但都指向内存中的相同字符串(零长度)对象。

所以在内部他们没有区别。这一切都归结为您或您的团队想要使用哪一个的便利性。字符串类的这种行为在 .NET Framework 中称为字符串实习。Eric Lippert 有一个非常好的博客在这里描述了这个概念。

于 2016-10-12T12:37:37.747 回答
11

几乎每个开发人员都会知道“”是什么意思。我个人第一次遇到 String.Empty 并且不得不花一些时间搜索谷歌以确定它们是否真的完全相同的东西。

于 2009-05-31T19:34:43.447 回答
11

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

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

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

于 2016-04-29T21:09:27.863 回答
9

以上任何一种。

有很多很多更好的事情要赞美。比如什么颜色的树皮最适合一棵树,我认为是模糊的棕色,带有淡淡的苔藓色。

于 2008-11-04T19:50:53.453 回答
7

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

于 2009-01-22T17:03:09.630 回答
7

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

于 2012-05-24T16:16:36.840 回答
6

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

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

我不会在代码中使用字符常量“”,而是string.EmptyString.Empty容易理解程序员的意思。

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

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

于 2008-11-04T20:00:50.487 回答
6

我会赞成string.EmptyString.Empty因为您可以使用它而无需using System;在文件中包含 a 。

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

于 2015-06-10T14:13:14.083 回答
5

我没有区别。最后一个是最快的输入虽然:)

于 2008-11-04T19:52:56.523 回答
5

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

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

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

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

于 2010-08-31T21:52:36.813 回答
4

没关系——它们是完全一样的。但是,最重要的是你必须保持一致

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

于 2008-11-04T20:01:25.087 回答
4

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

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

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

如果您输入“”,而您的意思是“”,反之亦然,编译器会愉快地执行您告诉它的操作。其他开发人员可能也可能无法收集您的特定意图。已创建错误。

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

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

特异性和编译时执行。这是晚饭吃的。

于 2017-05-18T15:44:15.853 回答
3

我使用第三个,但在其他两个中,第一个似乎不那么奇怪。string 是 String 的别名,但在作业中看到它们会让人感觉不舒服。

于 2008-11-04T19:51:36.293 回答
3

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

[编辑]

此外,您可能希望始终使用其中一个stringString以保持一致性,但这只是我。

于 2008-11-04T19:55:19.873 回答
3

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

于 2017-05-24T17:14:22.373 回答
2

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

于 2008-11-04T19:52:02.143 回答
2

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

考虑以下 C# 代码...

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

对比

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

我个人觉得后者不那么模棱两可,更容易阅读。

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

于 2017-01-10T16:11:03.353 回答
1

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

于 2008-11-04T19:52:04.340 回答
1

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

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

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

于 2008-11-05T07:12:38.837 回答
1

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

正如大卫暗示的那样, 和 之间的差异String.Empty非常""小,但还是有区别的。""实际上创建了一个对象,它很可能会被从字符串实习生池中拉出来,但仍然......虽然String.Empty没有创建任何对象......所以如果你真的在寻找最终的内存效率,我建议String.Empty。但是,您应该记住,差异是如此微不足道,您将永远不会在您的代码中看到它......
至于System.String.Emptystring.EmptyString.Empty......我的关心水平很低;-)

于 2011-11-16T02:28:27.170 回答
1

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

于 2017-12-10T19:44:57.500 回答
0

可能是一个有争议的评论,但总的来说,我发现当我与 Microsoft 保持一致时,我的生活会更轻松。我们不可能知道他们为什么做事的全部深层原因(有时非常严格,有时很笨拙,我想)。

他们在自动生成的文件(如程序集文件)中使用“”,这就是我所做的。事实上,当我尝试用 String.Empty 替换 "" 以下的任何内容时,Visual Studio 崩溃了。对此可能有一个合乎逻辑的解释,但以我有限的知识,如果我只是按照他们所做的那样做,大多数情况下,事情都会解决。(相反:我知道他们一些自动生成的文件也使用 String.Empty,这打破了我的观点。:))

<Assembly: System.Reflection.AssemblyCulture("")>
<Assembly: System.Reflection.AssemblyDescription("")>
<Assembly: System.Reflection.AssemblyFileVersion("1.0.0.0")>
<Assembly: System.Reflection.AssemblyKeyFile("")>
<Assembly: System.Reflection.AssemblyProduct("")>
<Assembly: System.Reflection.AssemblyTitle("")>
于 2020-04-05T14:54:33.640 回答