在C#中,我应该使用string.Empty或String.Empty或""来初始化字符串吗?

Dan*_*der 689 .net c# string initialization

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

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

string willi = string.Empty;
Run Code Online (Sandbox Code Playgroud)

要么

string willi = String.Empty;
Run Code Online (Sandbox Code Playgroud)

要么

string willi = "";
Run Code Online (Sandbox Code Playgroud)

或者是什么?

Jon*_*eet 792

使用您和您的团队认为最具可读性的任何内容.

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

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

该参数""" "很容易误认为对方并没有真正和我一起洗.除非你使用比例字体(并且我没有与任何开发人员合作过),否则很容易区分它们.

  • @tvanfosson:你(或同事)真的被这个臭虫咬了吗?我怀疑这种说法没有它实际上造成了问题.我已经使用""多年而没有弄错... (119认同)
  • 你给了我灵感,开始在Times New Roman开发. (77认同)
  • 当你期望看到""你很容易误认为""为""时,你的眼睛会欺骗你.这就是为什么编辑别人写的东西更容易的原因.你的大脑没有关于文本的先入为主的想法,因此更容易挑选出异常. (75认同)
  • 对于某些[不明原因`string.Empty`不是常数](http://stackoverflow.com/questions/507923/).这意味着在许多需要编译时常量的情况下,`string.Empty`甚至都不合法.这包括`case""`**switch`**语句中的块,**可选参数的默认值**,应用**属性**的参数和属性,以及许多其他情况(留给读者) ).因此,在某些常见情况下不允许使用`string.Empty`,最好使用``"`-everywhere约定. (72认同)
  • 就个人而言,我总是使用String.Empty,每当我想在字符串上使用静态方法时,我都使用大写'S',它只是一个允许我区分类型和变量的个人首选项.但这只是在java的commons.lang中使用StringUtils.EMPTY的结转.一个兴趣点是我几乎失明了,这对我的可读性肯定有帮助. (34认同)
  • @Alan:我会尝试看看它是什么样的.就个人而言,我使用空格而不是制表符(并且会为了死而战斗;)我怀疑这对于排列位参数等不太好...但值得一试. (20认同)
  • string.Empty的最大优点是您可以在诸如Visual Studio之类的IDE中更轻松地找到它的精确用法.""的简单"查找"操作将返回转义中的转义引号和""表示以及您实际需要的用法.执行string.Empty的"find usages"代码检查类型将获得解决方案范围内的所有用法,其中查找字符串文字(如"")的用法仅限于程序集的范围定义于. (17认同)
  • 就个人而言,我发现我的大脑使用更少的能力来解释一个简单的模式`""`而不是String.Empty("嘿,有一个类和一个属性 - 它在做什么?")使用String.Empty的每个人是否也使用String.空间(1)?如果没有难以区分的空间,那么也可能是一个或多个. (14认同)
  • @MutantNinjaCodeMonkey:我记不起在代码库中搜索"",如果我这样做,我在评论或逐字字符串文字中使用""就足够小了,以至于不会打扰我.如果这确实是`string.Empty`的最大优势,那么这是一个非常微不足道的IMO. (6认同)
  • Jon,我在VS中使用Segoe UI 10 pt.无论如何,美丽的标签完美排列,我可以用这种方式更长的线条.也许我不是开发人员:D (5认同)
  • 为什么要冒这个机会?因为我发现""比string.Empty更具可读性.否则我肯定会使用后者.鉴于一个明确的个人偏好与一个从未咬过我的潜在风险,我认为找到团队认为最具可读性的代码是合理的. (5认同)
  • @gehho:*你*发现它的可读性较差 - 而且没关系 - 但我发现**比`string.Empty`更可读.使用等宽字体,""和""之间的区别对我来说非常清楚,并且`string.Empty`不必要地混乱.但这真的只是个人偏好. (5认同)
  • 我认为"问题"并不是它*引入了错误*(我也从未有过),但是它的可读性较低*并且你有时必须*看两次*是否将字符串初始化为空字符串` ""或"空间""".当然,将字符串初始化为空格是非常罕见的,但我仍然经常在无意识中检查它.因此,我总是使用`String.Empty`,因为从第一眼看就清楚了. (4认同)
  • 唯一可能的混淆点是在一个双引号和两个单引号之间...("vs'')== WTF!?!?!任何"称职的"程序员都会轻易地处理EITHER var s =""OR var s = String.Empty.但仔细阅读这里的评论......很高兴看到其他人对程序风格有一些模棱两可,准宗教信仰的确认,这对于老鼠的土豆皮并不重要.我以为我一个人叹了口气 (3认同)
  • 关于节目偏好的辩论就像辩论食物偏好一样.不可能比另一个更好地证明一个,因为使用它的人没有_practical_差异.可以肯定的是,当他们不得不改变他们的习惯时,一个人对另一个人的一致使用会在不确定性方面造成一点点困难,但事实上,可变性应该让每个人都有自由发展自己的习惯.虽然这种选择的自由导致了更多的战争(无论是武装还是火焰). (3认同)
  • 我还使用Javascript,VBScript,SQL和VB6开发...而string.Empty可能仅适用于.Net,""(或"")可以在任何地方使用.我喜欢使用"",只是为了在同一产品中使用不同语言的一致性. (3认同)
  • ``"`看起来不像````,但它可能与''''`混淆. (2认同)

aBe*_*mer 373

从性能和代码生成的角度来看,确实没有区别.在性能测试中,它们之间来回徘徊,其间哪一个比另一个快,并且只有毫秒.

在查看幕后代码时,您实际上也看不出任何差异.唯一的区别在于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;
}
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)
.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
Run Code Online (Sandbox Code Playgroud)

汇编代码

        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 
Run Code Online (Sandbox Code Playgroud)
        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 
Run Code Online (Sandbox Code Playgroud)

  • @PrateekSaluja:要查看IL,您可以使用Visual Studio附带的ildasm.exe.要查看反汇编,请在遇到断点时使用调试菜单上的"反汇编"窗口(也适用于版本代码). (13认同)

Kon*_*lph 78

最好的代码根本就没有代码:

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

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

  • 我同意代码应该尽可能小,但通常不会认为较少的字符总是更好的代码.例如,当谈到变量命名时,合理数量的字符通常会产生比仅使用i和j更好的名称. (28认同)
  • 对我来说: string.Empty 表示该字符串始终为空,而“”表示在编写此字符串时该字符串可能为空,但您可以自由更改它。 (4认同)
  • @Markus高度依赖:对于表示索引的循环变量,`i`**比长变量名更好.更一般地,以相同的清晰度传达相同信息*的较短变量名*总是优选的.只是表达你需要*某个字符长度的必要信息,我不否认这个(没有人). (3认同)
  • 但在 C# 中,我们只能说 string.IsNullOrWhitespace(s) :p (2认同)
  • @Konrad:只有当循环很小并且它不包含任何其他索引时,我才是一个好的变量名.但我同意,如果...... 可以更简单地说明相同的信息,这些信息是可取的,比如在string.Empty /""情况下.string.Empty不会增加任何清晰度. (2认同)
  • 简洁性永远应该被可读性所压倒。框架开发人员添加“String.Empty”是有原因的,这不仅仅是为了性能问题,也是为了清楚地表明其意图是什么。在扫描代码时,它比“””更容易识别(和搜索)。 (2认同)

Men*_*tus 53

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

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

  • `switch`语句就是一个非常好的例子.另外,如果你创建一个可选参数,比如`void MyMethod(string optional =""){...}`,它也不可能使用`string.Empty`.当然,如果你想定义一个`const`字段或局部变量,`const string myString ="";`再次``"`是唯一的选择.如果只有`string.Empty`是一个常量字段,那就没有区别了.但事实并非如此,所以在某些情况下你必须使用""".那么为什么不一直使用"""? (21认同)
  • 这是一个非常强大的参数,因为使用`string.Empty`会阻止您在代码库中获得**一致性**:您必须使用两个不同的实体来表达相同的内容.并添加到你不能做的事情列表:你不能使用带有**属性的`string.Empty`**. (5认同)
  • 非常好点!链接坏了.以下是内容的副本:http://web.archive.org/web/20131230161806/http://kossovsky.net/index.php/2009/06/string-empty-versus-empty-quotes/ (2认同)

Jim*_*mmy 42

我宁愿stringString.选择string.Empty""是选择一个,并与它坚持的问题.使用的优点string.Empty是你的意思非常明显,你不会意外地复制"\x003"在你的不可打印的字符"".

  • 我认为,如果你不小心将不可打印的字符复制到代码中,那么问题就比这个问题更大;) (99认同)
  • ASCII\003恰好是我用过的B2B消息的字段分隔符:) (9认同)
  • (我还建议避免使用\ x转义,顺便说一句 - 很难发现"\ x9Bad编译器"和"\ x9Good编译器"之间的区别,它们*具有*根本*不同的结果!) (7认同)
  • 您使用复制/粘贴来输入 `""`...? (3认同)
  • @Jimmy当然,但我们在讨论空字符串.我声称,当复制/粘贴无效时,"""是危险的论点,因为你永远不会复制/粘贴空字符串.对于其他字符串,当然总是需要注意的事项. (2认同)

Joh*_*udy 22

我不打算进入,但我看到一些错误的信息被扔到这里.

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

正如一些人所说,没有什么区别之间的所有string.EmptyString.Empty.

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

  • 我不明白为什么"技术上"每个""的实例都会创建一个对象.这不仅仅是字符串被插入的机会 - 它在C#规范中. (20认同)

Mid*_*Gun 15

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


小智 13

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

""我而言,我不太确定.

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


Jas*_*ker 10

几乎每个开发人员都会知道""意味着什么.我个人遇到的String.Empty在第一时间,不得不花一些时间搜索谷歌弄清楚,如果他们真的完全一样的事情.

  • 你错过了@Jason的观点.你怎么知道第一次看到`string.Empty`是什么?你知道第一次看到它是什么吗? (5认同)
  • 它是一个公共只读字符串字段,其值为""......为什么会改变? (3认同)

Ste*_*eve 10

这个话题很老很长,请原谅我这个行为是否已经在其他地方提到过了.(并指出我的答案)

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

在初始化的情况下,string.Empty然后编译器警告

CS0219 - The variable 'x' is assigned but its value is never used
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 有趣。请注意,声明“ var used =“ literal”;`可以由编译器完全优化(删除)。它没有副作用。另一方面,不能完全删除“ var used = MyClass.Member;”。那是因为读`Member`可能会有副作用。如果`Member`是具有`get`访问器的静态属性,则很明显,必须保留对getter的调用。但是即使`Member`是一个静态字段,静态构造函数可能也会运行。肯定会有这种方式。但是您需要一个哑元来读取`Member`。 (2认同)

RBT*_*RBT 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
}
Run Code Online (Sandbox Code Playgroud)

这清楚地表明,所有三个变量,即str1,str2str3虽然使用不同的语法被初始化都指向完全相同的字符串中存储对象(零长度的).我在.NET 4.5控制台应用程序中执行了此测试.所以内部他们没有区别,这一切都归结为你想用作程序员的方便性.字符串类的这种行为在.NET中称为字符串实习.Eric Lippert 在这里有一个非常好的博客描述了这个概念.


Qui*_*ome 8

以上任何一种.

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


小智 7

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


zen*_*dar 6

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

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

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

stringString我喜欢小写string更多的只是因为我曾经与德尔福合作了很多年,德尔福的风格是小写string.

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


小智 6

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


小智 5

我没有什么区别.最后一个是尽快输入:)


mck*_*mey 5

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

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

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

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


小智 5

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

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

  • 我是团队的唯一成员,我该如何决定?扔骰子? (2认同)
  • 对于那些可能想知道如何在不导入“using System”命名空间的情况下使用“string.Empty”常量的人 - C# 中的关键字只需转换为其完全限定名称,其中包括命名空间,然后再编写为 MSIL在输出 *.dll 或 *.exe 文件中。因此,编译器实际上将“string.Empty”写入 MSIL 中的“System.String.Empty”。正如您可能已经知道的那样,如果您提到完全限定的类型名称,那么您可以跳过在代码文件顶部导入命名空间。 (2认同)