C#在声明非空字符串时是否会隐式分配一个空字符串?

4
我关注了一个关于2011年之前的旧回答的评论:不可变字符串

在那里声称这段代码
string str="a";
str +="b";
str +="c";
str +="d";
str +="e";

console.write(str) //output: abcde

在内存中创建了10个字符串:
"", "a", "b", "c", "d", "e", "ab", "abc", "abcd", and "abcde"

虽然我理解为什么会发生这种情况,但我仍然无法理解为什么首先会有一个“”字符串。有人可以给我提示吗?也许这甚至不是问题所在? C#文档对这个问题没有任何说明。 我唯一的猜测是,C#的字符串是一个引用类型,因此默认情况下它是null,但是...在这个例子中,它在最开始就获得了一个值,所以我感到有些困惑。

3
我看不出任何原因导致空字符串 "" 被分配。 - TheGeneral
2
链接到实际答案。在评论中,实际声明已经说明,但没有解释:https://dev59.com/iGw05IYBdhLWcg3w9mdW#6921113 - Rotem
4
这句话的意思是:关于包括 "" 在内的10个字符串的假设只是一条没有任何证据支持的注释。我想知道这是否可以被认为是理所当然的。 - Mong Zhu
2
是的,我对一个没有引用的七年前的评论非常怀疑。基于这样的评论提出问题在我看来不是一个好主意。 - Ian Kemp
2
String.Empty是预定义的,并且可能出现在任何列出“内存中的字符串”的诊断工具中。它在此代码中未被使用。 - Hans Passant
显示剩余4条评论
1个回答

5
答案是:不会。
如果你反编译一个发布版本生成的代码,你会看到类似这样的内容:
private static void Main()
{
    Console.WriteLine(string.Concat(string.Concat(string.Concat(string.Concat("a", "b"), "c"), "d"), "e"));
}

这段代码生成的IL如下所示:
IL_0000: ldstr "a"
IL_0005: ldstr "b"
IL_000a: call string [mscorlib]System.String::Concat(string,  string)
IL_000f: ldstr "c"
IL_0014: call string [mscorlib]System.String::Concat(string,  string)
IL_0019: ldstr "d"
IL_001e: call string [mscorlib]System.String::Concat(string,  string)
IL_0023: ldstr "e"
IL_0028: call string [mscorlib]System.String::Concat(string,  string)
IL_002d: call void [mscorlib]System.Console::WriteLine(string)
IL_0032: ret

正如您所看到的,这里没有使用空字符串。

(为了更好地支持调试器,调试版本生成的代码略有不同,但仍然不会创建空字符串。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接