String.Empty和""(空字符串)有什么区别?

joh*_*hnc 278 .net string double-quotes

在.NET中,String.Empty和之间的区别是什么"",它们是可互换的,还是存在一些基本的参考或本地化问题,这些问题String.Empty将确保不是问题?

Bri*_*ndy 286

在版本2.0之前的.NET中,""创建一个对象而不string.Empty创建对象引用,这样可以string.Empty提高效率.

在.NET 2.0及更高版本中,所有出现的""引用都是相同的字符串文字,这意味着""相当于.Empty,但仍然没有那么快.Length == 0.

.Length == 0是最快的选择,但.Empty代码稍微清晰.

有关更多信息,请参阅.NET规范.

  • 由于字符串实习,""只会创建一个对象.基本上,性能权衡是花生 - 可读性更重要. (90认同)
  • 有趣的是,即使问题没有说明将字符串与""或string.Empty进行比较以检查空字符串,很多人似乎都在解释这个问题...... (12认同)
  • @JeffreyHarmon:或者你可以使用`string.IsNullOrEmpty(stringVar)`. (11认同)
  • 我会小心.Length == 0,因为如果你的字符串变量为null,它可以抛出异常.如果你用""来检查它,它将正确地返回false,没有例外. (10认同)
  • 如果有人想防止测试空字符串的不良做法,您可以在代码分析中启用 CA1820。https://docs.microsoft.com/visualstudio/code-quality/ca1820-test-for-empty-strings-using-string-length (2认同)

Hab*_*bib 189

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

switch语句中的case表达式

string str = "";
switch(str)
{
    case string.Empty: // Error: A constant value is expected. 
        break;

    case "":
        break;

}
Run Code Online (Sandbox Code Playgroud)

属性参数

[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression 
//        or array creation expression of an attribute parameter type
Run Code Online (Sandbox Code Playgroud)

  • 有趣的是,我不认为这个老问题会得到任何相关的新信息.我错了 (20认同)

cha*_*ers 41

以前的答案对于.NET 1.1是正确的(查看他们链接的帖子的日期:2003).从.NET 2.0及更高版本开始,基本上没有区别.无论如何,JIT最终会引用堆上的相同对象.

根据C#规范,第2.4.4.5节:http://msdn.microsoft.com/en-us/library/aa691090( VS.71) .aspx

每个字符串文字不一定会产生新的字符串实例.当两个或多个根据字符串相等运算符(第7.9.7节)等效的字符串文字出现在同一个程序集中时,这些字符串文字引用相同的字符串实例.

有人甚至在Brad Abram的帖子中提到了这一点

总之,""与String.Empty的实际结果是零.JIT最终会弄明白.

我个人认为,JIT比我更聪明,所以我尽量不要对这样的微编译器优化过于聪明.JIT将展开()循环,删除冗余代码,内联方法等,比我或C#编译器可以预先预测的更合适的时间.让JIT完成它的工作:)


Jam*_*ing 35

String.Empty是一个只读字段,""而是一个常量字段.这意味着您不能String.Empty在switch语句中使用它,因为它不是常量.

  • @Enzoaeneas “默认”字符串为空,而不是空。所有引用对象的“默认”都是 null。 (3认同)

Bru*_*nez 18

另一个区别是String.Empty生成更大的CIL代码.虽然引用""和String.Empty的代码长度相同,但编译器不会针对String.Empty参数优化字符串连接(请参阅Eric Lippert的博客文章).以下等效功能

string foo()
{
    return "foo" + "";
}
string bar()
{
    return "bar" + string.Empty;
}
Run Code Online (Sandbox Code Playgroud)

生成这个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 
}
Run Code Online (Sandbox Code Playgroud)

  • 使用三元运算符并不罕见:`"bar" + (ok ?"" : "error")` (4认同)

Eug*_*atz 13

上面的答案在技术上是正确的,但你真正想要使用的是,为了获得最佳的代码可读性和最小的异常机会,String.IsNullOrEmpty(s)

  • 在平等比较方面,我完全同意,但问题还在于两个概念之间的区别以及比较 (3认同)
  • 请注意,“发生异常的可能性最小”通常意味着“继续但做错事的可能性最大”。例如,如果您正在解析一个命令行参数,并且有人使用 `--foo=$BAR` 调用您的应用程序,那么您可能想找出他们忘记设置环境变量和他们没有传递标志之间的区别根本不。`string.IsNullOrEmpty` 通常是一种代码味道,表明您没有正确验证输入或正在做奇怪的事情。当您真正打算使用“null”或类似 Maybe / Option 类型的内容时,通常不应该接受空字符串。 (3认同)

The*_*vil 9

我倾向于使用String.Empty而不是""一个简单但不明显的原因: "????????????????????"并且""不一样,第一个实际上有16个零宽度字符.显然,没有一个有能力的开发人员会在他们的代码中放入零宽度字符,但如果他们确实进入那里,那么这可能是一个维护噩梦.

笔记:


Est*_*aya 6

String.Empty不会创建对象,而""会创建对象.然而,正如这里指出的那样,差异是微不足道的.

  • 如果检查string.Empty或""的字符串,这并不简单.Eugene Katz指出,人们应该使用String.IsNullOrEmpty.否则你会得到意想不到的结果. (4认同)

Jas*_*son 6

""的所有实例都是相同的,实际的字符串文字(或它们应该是).因此,每次使用""时,你真的不会在堆上抛出一个新对象,而只是创建对同一个实体对象的引用.话虽如此,我更喜欢string.Empty.我认为它使代码更具可读性.


Moj*_*ian 6

使用String.Empty而不是"".

这比速度比内存使用更多,但它是一个有用的提示.这 ""是一个文字,因此将作为文字:在第一次使用时它被创建,并且对于以下用途,它的引用被返回.""无论我们使用它多少次,只有一个实例存储在内存中!我没有看到任何记忆惩罚.问题是每次""使用时,都会执行一个比较循环来检查它 ""是否已经在实习池中.另一方面,String.Empty 是对""存储在.NET Framework内存区域中的引用. String.Empty指向VB.NET和C#应用程序的相同内存地址.那么为什么每次需要"" 时都会搜索引用String.Empty

参考:String.Emptyvs""

  • 自 .net 2.0 起就不是这样了 (4认同)