附加到空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);
当一个或两个操作数是
string
types时,二元+
运算符执行string连接。 如果string连接的操作数为null
,则replace空string。 否则,通过调用从object
typesinheritance的虚拟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。