String.Empty和“”(空string)有什么区别?
在.NET中, String.Empty
和""
之间有什么区别,它们是可以互换的,还是在String.Empty
确保不会有问题的情况下,存在一些底层引用或本地化问题?
在2.0之前的.NET中, ""
在string.Empty
创build一个对象时不创build对象ref ,这使得string.Empty
效率更高。
在.NET 2.0及更高版本中,所有出现的""
都是指相同的string,这意味着""
等于.Empty
,但仍不如.Empty
.Length == 0
那样快。
.Length == 0
是最快的选项,但是.Empty
使得代码稍微更清晰。
有关更多信息,请参阅.NET规范 。
String.Empty和“”之间的区别是什么,它们是可以互换的
string.Empty
是一个只读字段,而""
是一个编译时间常量。 他们performance不同的地方是:
C#4.0或更高版本中的默认参数值
void SomeMethod(int ID, string value = string.Empty) // Error: Default parameter value for 'value' must be a compile-time constant { //... implementation }
在switch语句中的caseexpression式
string str = ""; switch(str) { case string.Empty: // Error: A constant value is expected. break; case "": break; }
属性参数
[Example(String.Empty)] // Error: An attribute argument must be a constant expression, typeof expression // or array creation expression of an attribute parameter type
以前的答案是正确的.NET 1.1(看他们链接的post的date:2003年)。 从.NET 2.0及更高版本开始,基本没有区别。 无论如何,JIT将最终引用堆上的同一个对象。
根据C#规范,第2.4.4.5节: http : //msdn.microsoft.com/en-us/library/aa691090( VS.71) .aspx
每个string文字不一定会导致新的string实例。 当根据string相等运算符(第7.9.7节)出现的两个或多个string文本出现在同一个程序集中时,这些string文本引用同一个string实例。
有人甚至在布拉德·阿布拉姆的post的评论中提到这一点
总之,“”与String.Empty的实际结果是零。 JIT将最终弄清楚。
我个人发现,JIT比我聪明,所以我尽量不要像这样的微编译器优化太聪明。 JIT将展开()循环,更好地在更合适的时间去除多余的代码,内联方法等,而不是我或C#编译器事先预料到的。 让JIT做好工作:)
String.Empty
是一个只读字段,而""
是一个const 。 这意味着你不能在switch语句中使用String.Empty
,因为它不是一个常量。
另一个区别是String.Empty生成较大的CIL代码。 尽pipe引用“”和String.Empty的代码长度相同,但编译器并没有为String.Empty参数优化string连接(参见Eric Lippert的博客文章 )。 以下等效函数
string foo() { return "foo" + ""; } string bar() { return "bar" + string.Empty; }
生成这个IL
.method private hidebysig instance string foo() cil managed { .maxstack 8 L_0000: ldstr "foo" L_0005: ret } .method private hidebysig instance string bar() cil managed { .maxstack 8 L_0000: ldstr "bar" L_0005: ldsfld string [mscorlib]System.String::Empty L_000a: call string [mscorlib]System.String::Concat(string, string) L_000f: ret }
上面的答案在技术上是正确的,但是你真的想要使用什么,为了获得最好的代码可读性和最小的exception机会是String.IsNullOrEmpty(s)
使用String.Empty
而不是""
。
这比速度比内存使用更多,但它是一个有用的提示。
""
是一个文字,所以将作为一个文字:在第一次使用它被创build,并为以下用途返回它的引用。 无论使用多less次,只有一个""
实例将被存储在内存中! 我在这里没有看到任何记忆惩罚。 问题是每次使用""
,执行一个比较循环来检查""
是否已经在intern池中。 另一方面,String.Empty
是对存储在.NET Framework内存区域中的""
的引用。String.Empty
指向VB.NET和C#应用程序的相同内存地址。 那么为什么每当你需要在String.Empty
中引用这个引用的时候search一个引用呢?
参考: String.Empty
与""
String.Empty不创build一个对象,而“”。 不过,正如这里指出的那样,这个差别是微不足道的。
“”的所有实例是相同的,实际的string文字(或者他们应该是)。 因此,每次使用“”时,实际上不会在堆上抛出一个新对象,而只是创build对同一个被禁止对象的引用。 话虽如此,我更喜欢string.Empty。 我认为它使代码更具可读性。
这只是没关系!
过去的一些讨论:
http://www.codinghorror.com/blog/archives/000185.html
我倾向于使用String.Empty
而不是""
作为一个简单但不明显的原因: ""
和""
是不一样的,第一个实际上有16个零宽字符。 很显然,没有一个能干的开发人员会把宽度不足的字符放到代码中,但是如果他们真的进入代码,这可能是一个维护的噩梦。
笔记:
-
在这个例子中,我使用了U + FEFF 。
-
不知道是否要吃这些字符,而是用许多零宽度字符之一自己尝试
-
我只是来到这个感谢https://codegolf.stackexchange.com/
string mystring = ""; ldstr ""
ldstr
将新对象引用推送到存储在元数据中的string文字。
string mystring = String.Empty; ldsfld string [mscorlib]System.String::Empty
ldsfld
将静态字段的值推送到评估堆栈上
我倾向于使用String.Empty
而不是""
因为恕我直言,它更清晰,更less的VB – ish。
从entity framework的angular度来看:EF版本6.1.3在validation时似乎将String.Empty和“”区别对待。
string.Empty被视为一个空值用于validation目的,如果在Required(归属)字段上使用,则会抛出validation错误; “”将通过validation,而不是抛出错误。
EF 7+中可能会解决此问题。 参考: – https://github.com/aspnet/EntityFramework/issues/2610 )。
编辑:[必需(AllowEmptyStrings = true)]将解决此问题,允许string.Emptyvalidation。
由于String.Empty不是编译时常量,因此不能将其用作函数定义中的默认值。
public void test(int i=0,string s="") { // Function Body }
这里的每个人都给了一些很好的理论上的阐明 我也有类似的疑问。 所以我尝试了一个基本的编码。 我发现有一个区别。 这是区别。
string str=null; Console.WriteLine(str.Length); // Exception(NullRefernceException) for pointing to null reference. string str = string.Empty; Console.WriteLine(str.Length); // 0
所以看起来“空”意味着绝对无效&“String.Empty”意味着它包含某种价值,但它是空的。