在C#中,我想用空字符串初始化字符串值。
我该怎么做? 什么是正确的方法,为什么?
string willi = string.Empty;
或
string willi = String.Empty;
或
string willi = "";
或者什么?
答案 0 :(得分:763)
使用您和您的团队最易读的内容。
其他答案表明,每次使用""
时都会创建一个新字符串。这不是真的 - 由于字符串实习,它将在每个程序集创建一次或每个AppDomain创建一次(或者可能在整个过程中创建一次 - 在前面不确定)。这种差异可以忽略不计 - 大规模,大量无关紧要。
您发现更具可读性是另一回事。它是主观的,因人而异 - 所以我建议你找出你团队中大多数人都喜欢的东西,并且所有人都认为这是为了保持一致性。我个人认为""
更容易阅读。
""
和" "
容易被误认为的论点并没有真正与我相提并论。除非你使用比例字体(我没有使用任何开发人员),否则很容易区分。
答案 1 :(得分:369)
从性能和代码生成的角度来看,确实没有区别。在性能测试中,他们在哪一个更快与另一个之间来回,并且只有毫秒。
在查看幕后代码时,你真的看不出任何区别。唯一的区别在于IL,string.Empty
使用操作码ldsfld
并且""
使用操作码ldstr
,但这只是因为string.Empty
是静态的,并且两个指令都做同样的事情。
如果你看一下生产的组件,它就完全一样了。
private void Test1()
{
string test1 = string.Empty;
string test11 = test1;
}
private void Test2()
{
string test2 = "";
string test22 = test2;
}
.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 :(得分:75)
The best code is no code at all:
编码的基本性质是,作为程序员,我们的任务是认识到我们做出的每一个决定都是权衡。 [...] 从简洁开始。根据测试要求增加其他尺寸。
因此,代码越少,代码就越好:首选""
到string.Empty
或String.Empty
。这两个六倍没有额外的好处 - 当然没有额外的清晰度,因为它们表达完全相同的信息。
答案 3 :(得分:51)
一个区别是,如果使用switch-case
语法,则无法编写case string.Empty:
,因为它不是常量。你得到一个Compilation error : A constant value is expected
请查看此链接以获取更多信息: string-empty-versus-empty-quotes
答案 4 :(得分:42)
我更喜欢string
到String
。选择string.Empty
超过""
是选择一个并坚持下去的问题。使用string.Empty
的好处是,您的意思非常明显,并且您不会意外地复制"\x003"
中不可打印的字符,例如""
。
答案 5 :(得分:22)
我不打算进入,但我看到一些错误的信息被扔到这里。
我个人更喜欢string.Empty
。这是个人偏好,我会根据具体情况与任何团队的意愿保持一致。
正如其他人所提到的,string.Empty
和String.Empty
之间没有任何区别。
此外,这是一个鲜为人知的事实,使用“”是完全可以接受的。在其他环境中,“”的每个实例都将创建一个对象。但是,.NET会中断其字符串,因此将来的实例将从实际池中提取相同的不可变字符串,并且任何性能损失都可以忽略不计。来源:Brad Abrams。
答案 6 :(得分:15)
我个人更喜欢“”,除非有充分的理由去做更复杂的事情。
答案 7 :(得分:13)
String.Empty
和string.Empty
是等效的。 String
是BCL类名; string
是它的C#别名(或快捷方式,如果你愿意的话)。与Int32
和int
相同。有关更多示例,请参阅the docs。
就""
而言,我不太确定。
就个人而言,我总是使用string.Empty
。
答案 8 :(得分:10)
几乎每个开发人员都会知道“”的意思。我个人第一次遇到String.Empty,不得不花一些时间搜索谷歌,弄清楚他们是否真的 完全一样。
答案 9 :(得分:9)
这个主题非常古老而且很长,所以如果在其他地方提到这种行为,请原谅。 (并指出我的答案)
如果您使用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
基本上,如果我做对了,他们希望允许程序员设置一个带有函数返回值的变量用于调试目的,而不会给他带来警告信息,因此只有在进行了大量的分配时才会限制警告和string.Empty不是常量而是字段。
答案 10 :(得分:8)
我在控制台应用程序中使用以下方法执行了这个非常简单的测试:
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
,str2
和str3
,但它们指向内存中完全相同的字符串(零长度)对象。我在.NET 4.5控制台应用程序中执行了此测试。所以内部他们没有区别,这一切都归结为你想用作程序员的方便性。字符串类的这种行为在.NET中称为 string interning 。 Eric Lippert有一个非常好的博客here来描述这个概念。
答案 11 :(得分:7)
以上任何一种。
有许多更好的事情需要教导。比如什么颜色的树皮最适合树,我认为模糊的棕色与青苔的色泽。
答案 12 :(得分:7)
我非常喜欢String.Empty,除了其他原因,以确保您知道它是什么,并且您没有意外删除内容, 但主要是为了国际化。 如果我在引号中看到一个字符串,那么我总是想知道这是否是新代码并且应该放入字符串表中。因此,每次代码更改/审核时,您都需要查找“引号中的内容”,是的,您可以过滤掉空字符串,但我告诉人们,除非您知道它不会被本地化,否则永远不要将字符串放在引号中
答案 13 :(得分:6)
string
是System.String
类型的同义词,它们是相同的。
值也相同:string.Empty == String.Empty == ""
我不会在代码中使用字符常量“”,而是使用string.Empty
或String.Empty
- 更容易看出程序员的意思。
在string
和String
之间我更喜欢小写string
,因为我多年来一直使用Delphi而且Delphi样式是小写的string
。
所以,如果我是你的老板,你会写string.Empty
答案 14 :(得分:6)
没有人提到在VisualStudio中字符串的颜色编码与字符串不同。这对可读性很重要。此外,小写通常用于变量和类型,但不是很大,但String.Empty是常量而不是var或类型。
答案 15 :(得分:5)
我没有任何区别。最后一个是键入最快的:)
答案 16 :(得分:4)
没关系 - 它们完全是一回事。 但是,主要的是你必须一致
P.S。我一直在为这种“什么是正确的东西”而斗争。
答案 17 :(得分:4)
这完全是一种代码风格的偏好,可以解决.NET如何处理字符串的问题。但是,这是我的意见:))
访问静态方法,属性和字段时,我总是使用BCL类型名称:String.Empty
或Int32.TryParse(...)
或Double.Epsilon
我在声明新实例时始终使用C#关键字:int i = 0;
或string foo = "bar";
我很少使用未声明的字符串文字,因为我希望能够扫描代码以将它们组合成可重用的命名常量。编译器无论如何都会用文字替换常量,所以这更像是一种避免魔术字符串/数字的方法,并且通过名称给它们带来更多意义。另外,更改值更容易。
答案 18 :(得分:4)
我赞成string.Empty
超过String.Empty
,因为您无需在文件中加入using System;
就可以使用它。
至于挑选""
超过string.Empty
,这是个人偏好,应由您的团队决定。
答案 19 :(得分:3)
前两个中的任何一个都可以被我接受。我会避免使用最后一个,因为通过在引号之间放置一个空格来引入错误相对容易。通过观察很难找到这个特殊的错误。假设没有拼写错误,所有语义都是等价的。
[编辑]
此外,您可能希望始终使用string
或String
来保持一致性,但这只是我。
答案 20 :(得分:3)
我使用第三个,但在其他两个中,第一个似乎不那么奇怪。 string是String的别名,但在分配中看到它们感觉不对。
答案 21 :(得分:3)
我亲眼目睹了#34;"导致(次要)问题两次。曾经是由于一个初级开发人员错误的基于团队的编程,另一个是一个简单的错字,但事实是使用string.Empty会避免这两个问题。
是的,这是一个非常多的判断调用,但是当一种语言为您提供多种方法时,我倾向于倾向于编译时监督最多且编译时强制最强的那种。那是不""。这完全是为了表达具体的意图。
如果键入string.EMpty或Strng.Empty,编译器会让您知道自己做错了。立即。它根本不会编译。作为开发人员,您引用特定的意图,编译器(或其他开发人员)无法以任何方式误解,并且当您做错时,您无法创建错误。
如果您键入" "当你的意思是""反之亦然,编译器很乐意做你告诉它做的事情。另一位开发人员可能会或可能不会收集您的具体意图。已创建错误。
在string.Empty之前很久我就使用了定义EMPTY_STRING常量的标准库。我们仍然在不允许使用string.Empty的case语句中使用该常量。
尽可能让编译器为您工作,并消除人为错误的可能性,无论多小。国际海事组织,这胜过可读性"正如其他人所引用的那样。
特异性和编译时执行。这是晚餐的原因。
答案 22 :(得分:2)
从长远来看,编译器应该使它们完全相同。选择一个标准,以便您的代码易于阅读,并坚持使用。
答案 23 :(得分:2)
我只是在查看一些代码,这个问题突然出现在我脑海中,我之前读过这篇文章。这当然是一个可读性问题。
考虑以下C#代码......
(customer == null) ? "" : customer.Name
VS
(customer == null) ? string.empty : customer.Name
我个人认为后者不那么模糊,更容易阅读。
正如其他人所指出的,实际差异可以忽略不计。
答案 24 :(得分:2)
我用""因为它会在我的代码中以鲜明的黄色着色......由于某种原因,String.Empty在我的Visual Studio Code主题中都是白色的。而且我认为这对我最重要。
答案 25 :(得分:1)
我认为第二个是“正确的”,但说实话,我认为这不重要。编译器应该足够聪明,可以将其中任何一个编译为完全相同的字节码。我用“”自己。
答案 26 :(得分:1)
在http://blogs.msdn.com/b/brada/archive/2003/04/22/49997.aspx上:
正如大卫所暗示的那样,
String.Empty
和""
之间的差异非常小,但存在差异。""
实际上创建了一个对象,它可能会从字符串实习池中拉出来,但仍然......String.Empty
没有创建对象...所以如果你真的在寻找内存效率,我建议String.Empty
。但是,你应该记住差异是如此微不足道,你将永远不会在你的代码中看到它...
至于System.String.Empty
或string.Empty
或String.Empty
...我的护理水平很低; - )
答案 27 :(得分:1)
空字符串就像空集,只是每个人用来调用""
的名称。同样在形式语言中,从长度为零的字母表创建的字符串称为空字符串。 set和string都有一个特殊的符号。空字符串:ε和空集:∅。如果你想谈论这个零长度字符串,你会称之为空字符串,所以每个人都知道你所指的是什么。现在,如果你将它命名为空字符串,为什么不在代码中使用string.Empty
,它表明意图是明确的。缺点是它不是一个常数,因此无处可用,如属性。 (由于某些技术原因,这不是常数,请参阅参考资料。)
答案 28 :(得分:0)
可能是一个有争议的评论,但是,总的来说,我发现与Microsoft保持一致可以使我的生活更轻松。我们可能不知道它们为什么会做事的全部深层原因(有时我认为很严格,有时很笨拙)。
他们在自动生成的文件(例如Assembly文件)中使用“”,这就是我要做的。实际上,当我尝试用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("")>
答案 29 :(得分:0)
我更喜欢""
,因为它更短并且String.Empty
解决了不存在的问题。
答案 30 :(得分:0)
虽然差异非常小,差异仍然存在。
1)“”创建对象,而String.Empty则不创建对象。但是这个对象将被创建一次,如果代码中有另一个“”,将在稍后从字符串池中引用。
2)字符串和字符串是相同的,但我建议使用String.Empty(以及String.Format,String.Copy等),因为点符号表示类,而不是运算符,并且以class开头字母符合C#编码标准。