之间的区别是什么串。空的,""(empty string)?
-
02-07-2019 - |
题
中。净之间的区别是什么 String.Empty
和 ""
, 和他们互换,或者是有一些潜在的参考或本地化问题上的平等, String.Empty
将确保不是一个问题吗?
其他提示
String.Empty和“"”之间的区别是什么? 可互换
string.Empty
是只读字段,而""
是编译时常量。他们表现不同的地方是:
C#4.0或更高版本中的默认参数值
void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
//... implementation
}
开关语句中的案例表达
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是正确的(查看他们链接的帖子的日期:2003)。从.NET 2.0及更高版本开始,基本上没有区别。无论如何,JIT最终会引用堆上的同一个对象。
根据C#规范,第2.4.4.5节: http://msdn.microsoft.com/en-us/库/ aa691090(VS.71)的.aspx
每个字符串文字不一定会产生新的字符串实例。当两个或多个根据字符串相等运算符(第7.9.7节)等效的字符串文字出现在同一个程序集中时,这些字符串文字引用相同的字符串实例。
有人甚至在布拉德·阿布拉姆的帖子的评论中提及这一点
总之,“”的实际结果是“与String.Empty为零。 JIT最终会弄明白。
我个人认为,JIT比我更聪明,所以我尽量不要对这样的微编译器优化过于聪明。 JIT将展开()循环,删除冗余代码,内联方法等,比我或C#编译器可以预先预测的更合适的时间。让JIT完成它的工作:)
String.Empty
是 readonly 字段,而""
是 const 。这意味着你不能在switch语句中使用 String.Empty
,因为它不是常量。
另一个区别是String.Empty会生成更大的CIL代码。而用于引用“”的代码则用于引用“和String.Empty长度相同,编译器不优化字符串连接(参见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
}
以上答案在技术上是正确的,但您可能真正想要使用的是,为了获得最佳代码可读性和最少的异常机会 String.IsNullOrEmpty(s)
我倾向于使用 String.Empty
而不是 ""
对于一个简单的,但不明显的原因:""
和 ""
不相同,第一个实际上有16零宽字。显然没有主管的开发是要把和零宽度人物进入他们的代码,但是如果他们得到在那里,它可以是一个维护的噩梦。
注:
我用 U+FEFF 在这个例子。
不知道,如果这样是要去吃那些字符,但是尝试它自己与许多零宽度人物
我只是来到这个谢谢 https://codegolf.stackexchange.com/
使用 String.Empty
而不是""
。
这比速度比内存使用更多,但它是一个有用的提示。该
中有该引用时""
是一个文字因此将作为一个文字:在第一次使用时它是 创建并为以下用途返回其引用。只有一个 无论我们多少次,""
的实例都将存储在内存中 用它!我没有看到任何记忆惩罚。 问题在于 每次使用""
时,执行比较循环以检查是否存在""
已经在实习池中。 另一方面,String.Empty
是对 .NET Framework内存区域中存储的""
的引用。String.Empty
指向VB.NET和C#的相同内存地址 应用。那么为什么每次需要""
时都要搜索引用 当您在String.Empty
?
String.Empty不会创建对象而“&”;确实。正如此处所指出的那样,差别是微不足道的,但是。
“”的所有实例是相同的,实习的字符串文字(或应该是)。因此,每次使用“"”时,你真的不会在堆上抛出新对象。但只是创建对同一个实体对象的引用。话虽如此,我更喜欢string.Empty。我认为它使代码更具可读性。
string mystring = "";
ldstr ""
ldstr
将新对象引用推送到存储在元数据中的字符串文字。
string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty
ldsfld
将静态字段的值推送到评估堆栈
我倾向于使用 String.Empty
而不是""
,因为恕我直言,它更清晰,更少VB-ish。
从实体框架的角度出发:EF版本6.1.3似乎处理String.Empty和“"”验证时有所不同。
string.Empty被视为用于验证目的的空值,如果在必需(属性)字段上使用它,则会抛出验证错误;在哪里作为“”将通过验证而不是抛出错误。
此问题可能在EF 7+中得到解决。参考: - https://github.com/aspnet/EntityFramework/issues/2610 )。
编辑:[必需(AllowEmptyStrings = true)]将解决此问题,允许string.Empty进行验证。
由于String.Empty不是编译时常量,因此不能将其用作函数定义中的默认值。
public void test(int i=0,string s="")
{
// Function Body
}
Eric Lippert 写道(2013年6月17日):
“我在C#编译器中使用的第一个算法是处理字符串连接的优化器。 不幸的是,在我离开之前,我没有设法将这些优化移植到Roslyn代码库;希望有人能够做到这一点!"
以下是截至2019年1月的一些 Roslyn x64 结果。尽管此页面上的其他答案达成了共识,但我认为当前的x64 JIT并未处理所有这些案例同样,当所有的事情都说完了。
但是,请特别注意,这些示例中只有一个实际上最终调用 String.Concat
,而我猜这是出于模糊的正确性原因(与优化疏忽相反)。其他差异似乎难以解释。
默认(字符串)  +  {default(String),  “",  String.Empty}
static String s00() => default(String) + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s01() => default(String) + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s02() => default(String) + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
<强>&QUOT;&QUOT; &NBSP; +&nbsp; {default(String),&nbsp; “&quot;,&nbsp; String.Empty}
static String s03() => "" + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s04() => "" + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s05() => "" + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
String.Empty&nbsp; +&nbsp; {default(String),&nbsp; “&quot;,&nbsp; String.Empty}
static String s06() => String.Empty + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s07() => String.Empty + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s08() => String.Empty + String.Empty;
mov rcx,[String::Empty]
mov rcx,qword ptr [rcx]
mov qword ptr [rsp+20h],rcx
mov rcx,qword ptr [rsp+20h]
mov rdx,qword ptr [rsp+20h]
call F330CF60 ; <-- String.Concat
nop
add rsp,28h
ret
测试详情
Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false
当您在视觉上扫描代码时,“&quot;字符串着色的方式显示为彩色。 string.Empty看起来像一个普通的class-member-access。在快速查看期间,更容易发现“”。或直觉的意思。
发现字符串(堆栈溢出着色并不完全有帮助,但在VS中这更为明显):
var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;
这里的每个人都给出了一些很好的理论澄清。我有类似的疑问。所以我尝试了一个基本的编码。我发现了一个区别。这就是区别。
string str=null;
Console.WriteLine(str.Length); // Exception(NullRefernceException) for pointing to null reference.
string str = string.Empty;
Console.WriteLine(str.Length); // 0
所以似乎“空”意味着绝对无效&amp; &QUOT;&的String.Empty QUOT;意味着它包含某种值,但它是空的。