Подтвердить что ты не робот

Как добавление пустой строки в С#?

Я был удивлен, увидев пример строки, инициализированной нулем, а затем добавив к ней что-то в производственной среде. Он просто плакал неправильно.

Я был уверен, что это вызвало бы исключение из нулевого объекта, но этот очень сокращенный пример также работает:

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

* Обратите внимание, что исходный код, который я нашел, устанавливает свойство string в null и добавляется к нему в другом месте, поэтому ответы, связанные с компилятором, оптимизирующим нуль во время компиляции, не имеют значения.

Может кто-нибудь объяснить, почему это работает без ошибок?

Последующий:

На основании ответа Leppie я использовал Reflector, чтобы увидеть, что внутри строки. 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 от Microsoft), не преобразуется в пустые строки, как это предлагается стандартами С# и большинством ответов, но использует несколько тестов для сокращения процесса, Конечный результат такой же, как если бы он был, но там вы идете:)

4b9b3361

Ответ 1

Оператор + для строк является только сокращением для string.Concat, который просто превращает аргументы null в пустые строки перед конкатенацией.

Update:

Обобщенная версия 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);
}

Ответ 2

Соответствующая цитата должна быть 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, заменяется пустая строка.

Ответ 3

это потому, что

В операциях конкатенации строк компилятор С# обрабатывает значение null строка такая же, как пустая строка, но она не преобразует значение исходной пустой строки.

От Как объединить несколько строк (руководство по программированию на С#)

Оператор binary + выполняет конкатенацию строк, когда один или оба операнды имеют тип string. Если операнд конкатенации строк null, заменяется пустая строка. В противном случае любая строка аргумент преобразуется в его строковое представление, вызывая виртуальный метод ToString, унаследованный от объекта типа. Если ToString возвращает null, заменяется пустая строка.

От Оператор добавления

Ответ 4

Вот что компилируется ваш код для

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.