附加到空string如何在C#中工作?

我惊讶地发现一个string被初始化为null的例子,然后在生产环境中添加了一些东西。 它只是闻到错误。

我确定它会抛出一个空对象exception,但这个大大减less的例子也适用:

string sample = null; sample += "test"; // sample equals "test" 

* 请注意,我发现的原始代码将string属性设置为null,并将其附加到其他位置,因此编译时优化编译时空值的编译器的答案是无关紧要的。

有人可以解释为什么这个工作没有错误?

跟进:

根据Leppie的回答,我使用了Reflector来查看string.Concat里面的内容。 现在真的很明显,为什么转换发生(没有魔术):

 public static string Concat(string str0, string str1) { if (IsNullOrEmpty(str0)) { if (IsNullOrEmpty(str1)) { return Empty; } return str1; } if (IsNullOrEmpty(str1)) { return str0; } int length = str0.Length; string dest = FastAllocateString(length + str1.Length); FillStringChecked(dest, 0, str0); FillStringChecked(dest, length, str1); return dest; } 

** 注意:我正在研究的特定实现(在Microsoft的.Net库中)并不像C#标准和大多数答案所build议的那样将其转换为空string,而是使用一些testing来缩短过程。 最终的结果是一样的,如果这样做,但你去:)

string的+运算符只是string.Concat缩写,它简单地将null参数转换为串联之前的空string。

更新:

string.Concat的通用版本:

 public static string Concat(params string[] values) { int num = 0; if (values == null) { throw new ArgumentNullException("values"); } string[] array = new string[values.Length]; for (int i = 0; i < values.Length; i++) { string text = values[i]; array[i] = ((text == null) ? string.Empty : text); num += array[i].Length; if (num < 0) { throw new OutOfMemoryException(); } } return string.ConcatArray(array, num); } 

相关的引用应该是ECMA- 334§14.7.4:

string连接:

 string operator +(string x, string y); string operator +(string x, object y); string operator +(object x, string y); 

当一个或两个操作数是stringtypes时,二元+运算符执行string连接。 如果string连接的操作数为null ,则replace空string。 否则,通过调用从objecttypesinheritance的虚拟ToString方法,将任何非string操作数转换为其string表示forms。 如果ToString返回null ,则replace空string。

这是因为

在string连接操作中,C#编译器将空string视为空string,但不转换原始空string的值。

从如何连接多个string(C#编程指南)

当一个或两个操作数是stringtypes时,二元+运算符执行string连接。 如果string连接的操作数为空,则replace空string。 否则,通过调用从objecttypesinheritance的虚拟ToString方法,将任何非string参数转换为其string表示forms。 如果ToString返回null,则replace空string。

来自Addition运算符

这是你的代码被编译到

 string sample = null; sample += "test"; 

被编译成这个IL代码:

 .entrypoint // Code size 16 (0x10) .maxstack 2 .locals init ([0] string sample) IL_0000: nop IL_0001: ldnull IL_0002: stloc.0 IL_0003: ldloc.0 IL_0004: ldstr "test" IL_0009: call string [mscorlib]System.String::Concat(string, string) IL_000e: stloc.0 IL_000f: ret 

String.Concat负责空string。