我很惊讶地看到一个字符串初始化为null然后在生产环境中附加了一些内容的示例。它只是闻到了错误。
我确信它会抛出一个空对象异常但是这个大大减少的例子也有效:
string sample = null;
sample += "test";
// sample equals "test"
* 注意我发现的原始代码将字符串属性设置为null并在其他地方附加到它,因此涉及编译器在编译时优化掉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#标准和大多数答案所建议的那样转换为空字符串,而是使用一些测试来快捷的过程。最终的结果和它一样,但是你去了:)
答案 0 :(得分:47)
字符串的+
运算符只是string.Concat
的简写,只是在连接之前将null
个参数转换为空字符串。
<强>更新强>
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);
}
答案 1 :(得分:7)
相关引文应为ECMA-334§14.7.4:
字符串连接:
string operator +(string x, string y); string operator +(string x, object y); string operator +(object x, string y);
二进制
+
运算符在一个或多个时执行字符串连接 两个操作数都是string
类型。 如果是字符串的操作数 连接是null
,空字符串被替换。否则,任何 非字符串操作数转换为其字符串表示形式 调用从类型ToString
继承的虚拟object
方法。如果ToString
返回null
,替换为空字符串。
答案 2 :(得分:3)
这是因为
在字符串连接操作中,C#编译器处理null 字符串与空字符串相同,但不转换该值 原始的空字符串。
来自How to: Concatenate Multiple Strings (C# Programming Guide)
binary +运算符在一个或两个时执行字符串连接 操作数是字符串类型。如果字符串连接的操作数是 null,替换空字符串。否则,任何非字符串 通过调用,将参数转换为其字符串表示形式 从类型对象继承的虚拟ToString方法。如果ToString 返回null,替换为空字符串。
答案 3 :(得分:1)
以下是您的代码编译为
的内容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
处理NULL字符串。