如何在c#中添加空字符串

本文关键字:添加 字符串 | 更新日期: 2023-09-27 18:12:46

我很惊讶地看到一个字符串被初始化为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;
}

**注意:我正在研究的具体实现(在微软的。net库中)不像c#标准和大多数答案所建议的那样转换为空字符串,而是使用一些测试来缩短过程。最终的结果是相同的,如果它做了,但你去:)

如何在c#中添加空字符串

字符串的+运算符只是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);
}

相关引语应为ECMA-334§14.7.4:

字符串连接:

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

二进制+操作符执行字符串连接,当一个或两个操作数都是string类型。如果是string的操作数连接是null,一个空字符串被替换。否则为any将非字符串操作数转换为其字符串表示形式调用从类型object继承的虚拟ToString方法。如果ToString返回null,替换为空字符串。

这是因为

在字符串连接操作中,c#编译器处理null与空字符串相同的字符串,但它不转换值

选自How to: concatate Multiple Strings (c# Programming Guide)

二进制+操作符在一个或两个操作符中执行字符串连接操作数为字符串类型。如果字符串连接的操作数是Null,一个空字符串被替换。否则,任何非字符串参数被转换为其字符串表示形式从对象类型继承的虚拟ToString方法。如果ToString返回null,一个空字符串被替换。

来自加法运算符

你的代码被编译成

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字符串