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