在C#中,我想用一个空字符串初始化一个字符串值。
我应该怎么做?正确的方法是什么,为什么?
string willi = string.Empty;
要么
string willi = String.Empty;
要么
string willi = "";
要不然是啥?
在C#中,我想用一个空字符串初始化一个字符串值。
我应该怎么做?正确的方法是什么,为什么?
string willi = string.Empty;
要么
string willi = String.Empty;
要么
string willi = "";
要不然是啥?
Answers:
使用您和您的团队最容易阅读的内容。
其他答案表明,每次使用时都会创建一个新字符串""
。这是不正确的-由于字符串内部操作,它会针对每个程序集创建一次,也可能针对每个AppDomain创建一次(或者可能对整个过程创建一次-不确定在那方面)。这种差异可以忽略不计-在很大程度上,在很大程度上是微不足道的。
但是,您发现更具可读性的是另一回事。它是主观的,并且因人而异-因此,我建议您了解团队中大多数人的喜好,并且所有人都希望保持一致。我个人觉得""
更容易阅读。
""
和" "
容易被彼此误解的论点并没有真正被我接受。除非您使用比例字体(并且我没有与任何使用过这种字体的开发人员合作),否则很容易分辨出区别。
string.Empty
它不是常数。这意味着在许多情况下需要编译时常量,string.Empty
甚至是不合法的。这包括语句中的case ""
块switch
,可选参数的默认值,应用属性时的参数和属性以及许多其他情况(留给读者阅读)。因此,鉴于string.Empty
在某些常见情况下不允许这样做,最好使用""
-everywhere约定。
从性能和代码生成的角度来看,确实没有什么区别。在性能测试中,它们之间来回切换得更快,只有几毫秒。
在查看幕后代码时,您实际上也看不到任何区别。唯一的区别在于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
编码的基本本质是,作为程序员,我们的任务是认识到我们做出的每个决定都是一个权衡。[…] 简洁起见。根据测试要求增加其他尺寸。
因此,更少的代码是更好的代码:不想""
给string.Empty
或String.Empty
。这两者的长度是原来的六倍,并且没有额外的好处-当然也没有增加的清晰度,因为它们表示的是完全相同的信息。
i
是不是一个长变量名更好。更通用的是,以相同的清晰度传达相同信息的较短的变量名总是可取的。只是为了表达必要的信息,您需要一定的字符长度,我并不否认这一点(没人可以)。
一个区别是,如果使用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
一个恒定的字段,就不会有任何区别。但这不是,因此在某些情况下,您必须使用""
。那么为什么不一直使用""
呢?
string.Empty
阻止您在代码库中实现一致性:您必须使用两个不同的实体来表示同一件事。要添加到您不能做的事情清单中:不能string.Empty
与attribute一起使用。
我宁愿string
到String
。选择string.Empty
了""
是选择一个,并与它坚持的问题。使用的好处string.Empty
是您的意思很明显,而且您不会意外地复制不可复制的字符(例如"\x003"
)""
。
""
我声称,复制/粘贴为空时很危险的参数,因为您永远不会复制/粘贴空字符串。对于其他字符串,当然总是要注意这一点。
我本来不会插话,但是我看到一些错误的信息被扔到这里。
我个人更喜欢string.Empty
。这是个人喜好,我会根据具体情况选择与我合作的任何团队。
正如其他人提到的,string.Empty
和之间没有任何区别String.Empty
。
另外,这是一个鲜为人知的事实,使用“”是完全可以接受的。在其他环境中,“”的每个实例都将创建一个对象。但是,.NET会保留其字符串,因此将来的实例将从内部存储池中提取相同的不可变字符串,并且任何性能损失都可以忽略不计。资料来源:布拉德·艾布拉姆斯(Brad Abrams)。
几乎每个开发人员都会知道“”的含义。我个人第一次遇到String.Empty,不得不花一些时间在Google上搜索以确定它们是否确实是同一回事。
string.Empty
什么?您知道""
第一次看到它是什么吗?
这个话题很老很长,如果在其他地方提到过这种行为,请原谅。(并指出涵盖该问题的答案)
如果使用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
基本上,如果我做对了,他们希望允许程序员设置具有函数返回值的变量用于调试目的,而不会在警告消息中打扰他,因此,他们仅在使用昂贵的分配和字符串的情况下才限制警告。空不是常数而是字段。
var unused = "literal";
可以由编译器完全优化(删除)。它没有副作用。另一方面,var unused = MyClass.Member;
不能完全删除。那是因为阅读Member
可能会有副作用。如果Member
是具有访问器的静态属性get
,则很明显必须保留对getter的调用。但是,即使Member
是静态字段,也可能会产生静态构造函数可能运行的副作用。肯定会有这种方式是不好的编码风格。但是你需要一个假人来阅读Member
。
我在控制台应用程序中使用以下方法执行了此非常简单的测试:
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中称为字符串实习。埃里克·利珀特(Eric Lippert)在这里有一个非常不错的博客,描述了这个概念。
除了其他原因之外,我强烈建议使用String.Empty,以确保您知道它是什么,并且您没有意外删除内容,但主要是为了国际化。如果我在引号中看到一个字符串,那么我总是不得不怀疑这是否是新代码,应该将其放入字符串表中。因此,每次代码更改/查看时,您都需要查找“引号中的内容”,是的,您可以过滤出空字符串,但是我告诉人们,除非您知道不会将字符串本地化,否则最好不要在引号中添加字符串。
没有人提到在VisualStudio中,字符串的颜色编码与字符串不同。这对于可读性很重要。另外,小写通常用于vars和type,不是什么大问题,但String.Empty是常量而不是var或type。
我宁愿这样做string.Empty
,String.Empty
因为您可以使用它而无需using System;
在文件中包含a 。
至于采摘""
了string.Empty
,这是个人喜好,应该由你的团队来决定。
string.Empty
不导入using System
名称空间的情况下使用常量的人来说,C#中的关键字只是简单地转换为包含名称空间的完全限定名称,然后在输出* .dll或*中将其作为MSIL编写。 exe文件。string.Empty
就像System.String.Empty
编译器在MSIL中一样有效地被编写。而且,您可能已经知道,如果提到完全限定的类型名称,则可以跳过在代码文件顶部导入名称空间的步骤。
我没有改变。最后一个虽然是打字最快的:)
没关系-它们是完全一样的东西。但是,最主要的是您必须保持一致
ps我一直都在为这种“什么是正确的事情”而苦恼。
前两个中的任何一个对我来说都是可以接受的。我将避免使用最后一个,因为通过在引号之间放置一个空格来引入bug相对容易。通过观察很难找到这个特定的错误。假设没有错别字,所有这些在语义上都是等效的。
[编辑]
另外,您可能希望始终使用string
或String
来保持一致性,但这仅是我自己。
我亲眼目睹了“”两次导致(次要)问题。一次是由于一个基于团队编程的初级开发人员的错误,另一个是简单的错字,但事实是使用字符串。Empty可以避免这两个问题。
是的,这在很大程度上是一种判断,但是当一种语言为您提供多种处理方式时,我倾向于倾向于编译器监督最多,编译时间执行最强的一种。那不是 “”。这都是关于表达特定意图的。
如果键入string.EMpty或Strng.Empty,编译器会告诉您您做错了。立即。它根本无法编译。作为开发人员,您要指出特定的意图,即编译器(或其他开发人员)不能以任何方式曲解,并且如果您做错了,就不能创建错误。
如果您在输入“”时键入“”,反之亦然,那么编译器会很乐意地执行您告诉它的操作。另一个开发人员可能会也可能无法收集您的特定意图。错误创建。
在string.Empty之前很久,我已经使用了定义EMPTY_STRING常量的标准库。我们仍然在case语句中使用该常量,其中不允许使用string.Empty。
尽可能使编译器为您工作,并消除人为错误的可能性,无论大小如何。IMO,这胜过其他人所引用的“可读性”。
特殊性和编译时间执行。晚餐是吃什么。
从长远来看,编译器应该使它们全部相同。选择一个标准,以便您的代码易于阅读并坚持下去。
尽管差异非常大,但差异仍然存在。
1)“”创建对象,而String.Empty不创建对象。但是,此对象将创建一次,并且如果代码中还有另一个“”,则稍后将在字符串池中对其进行引用。
2)字符串和字符串相同,但是我建议使用String.Empty(以及String.Format,String.Copy等),因为点表示法表示类,而不是运算符,并且以大写字母开头的类符合C#编码标准。
在http://blogs.msdn.com/b/brada/archive/2003/04/22/49997.aspx上:
正如David所暗示的,
String.Empty
和之间的差异""
很小,但是存在差异。""
实际上创建了一个对象,它很可能会从字符串实习生池中拉出,但仍然...虽然String.Empty
没有创建任何对象...所以我建议,如果您真的在寻找最终的内存效率String.Empty
。但是,请记住,差异是如此琐碎,以至于您永远都不会在代码中看到它……
至于System.String.Empty
或string.Empty
或String.Empty
……我的护理水平很低;-)