С# добавление строки + null не вызывает ошибку?
Как программист, я ожидал, что это вызовет исключение. Есть ли причина, по которой он обрабатывает null как ""?
string s = "hello";
string t = null;
Console.WriteLine(s + t);
Вывод:
Привет
Чтобы подчеркнуть мой вопрос, знаете ли вы, почему было принято решение об обращении null в String.Empty? Я ожидал добавления некоторой строки, но возникла проблема еще дальше, когда она не возвращала ее правильно, и она вернулась с нулевым значением. Проблема осталась незамеченной!
Здесь псевдокод, почему я думаю, что это плохо (и почему я был шокирован, чтобы не обнаружить ошибки):
Вы можете предположить, что я перегрузил ToString, чтобы указать имя человека или данные о них.
Person p = PersonDatabase.GetForName("Jimmy Gibbs");
Console.WriteLine("Name is: " + p.ToString());
Выдает исключение, поскольку p равно null
String p = PersonDatabase.GetForName("Jimmy Gibbs").Name;
Console.WriteLine("Name is: " + p);
Не генерирует исключение, хотя p равно null (он рассматривает его как "").
(Если вы хотите быть разборчивым и сказать, что я не смогу получить имя, поскольку GetforName будет null, подумайте об этом как:)
String p = PersonDatabase.GetNameFromID(1234); // Returns a string or null if not found
Console.WriteLine("Name is: " + p);
(Если вы используете это значение в списке или массиве, вы получите пустую запись, которая для меня сломалась, она создавала javascript и пыталась получить элемент по идентификатору "")
Ответы
Ответ 1
Из Спецификация языка С#:
7.8.4 Оператор добавления
Конкатенация строк:
оператор строки + (строка x, строка y); string operator + (строка x, объект y); string operator + (объект x, строка y);
Эти перегрузки бинарного + оператор выполняет конкатенацию строк. Если операнд конкатенации строк null, пустая строка замещенный. В противном случае любая нестрочная аргумент преобразуется в строку представления путем вызова виртуального Метод ToString, унаследованный от типа объект. Если ToString возвращает значение null, пустая строка.
Ответ 2
Оператор + испускается как string.Concat в результате IL.
s + t = string.Concat(s, t)
и при просмотре реализации он проверяет, являются ли аргументы null и возвращает string.Empty:
Разборка с отражателем:
[SecuritySafeCritical]
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;
}
Ответ 3
В операциях конкатенации строк компилятор С# обрабатывает пустую строку так же, как пустую строку, но не преобразует значение исходной нулевой строки. Дополнительная информация здесь http://msdn.microsoft.com/en-us/library/aa691375 (VS.71).aspx
Ответ 4
Когда мы думаем о принятом дизайнерском решении, мы должны смотреть не только на плюс оператора для строк, но и на связанные классы и методы, например. String.Concat(String, String) и StringBuilder.Append(String). Эти классы являются частью Base Class Library, которая широко используется в других языках (например, Visual Basic и F #).
С точки зрения дизайна языка и платформы все эти методы должны вести себя в согласованной фракции (т.е. обрабатывать нуль таким же образом). Я вижу три возможных варианта:
-
Выбросить исключение
Это "безопасное" решение, так как не ясно, что делать с нулем. В качестве компромисса для этого потребуется более защитный стиль программирования и более подробный код.
-
Используйте некоторое представление для нулевого, например. <null>
, null
или [null]
(стиль Java)
Это результат, которого вы ожидали. Непонятно, почему это должно произойти и как именно нуль должно быть представлено.
-
Обрабатывать null так же, как пустая строка (.NET-стиль)
Идея заключается в том, что текстовое представление null (т.е. отсутствующего объекта) является пустой строкой. В этом случае программист может использовать это поведение и писать более короткий код. С другой стороны, он может скрыть ошибки.
Было принято какое-то решение, и я думаю, что нет очевидного выбора. Ожидаемое поведение на С# и других языках .NET четко документировано и согласовано во всех методах, связанных с конкатенацией.
Ответ 5
Пользовательские операторы являются только статическими методами и, конечно, могут принимать параметры null
. Это, например, действительно полезно для делегатов.
Таким образом, принятие строки null
не является техническим, а конструктивным решением. И, вероятно, иногда полезно относиться к null
как "", так как много кода пользователя относится к ним одинаково.
Ответ 6
Если у меня есть оранжевый и добавьте еще один оранжевый, у меня теперь два апельсина.
Если у меня есть оранжевый и добавьте НИЧЕГО, у меня все еще есть оранжевый.
Мне нужно добавить NULL в строку и получить исходную строку, которая кажется совершенно интуитивной и семантической. NullReferenceExceptions должны быть зарезервированы при доступе к свойствам или методам экземпляра для экземпляров, которые не существуют, например.
string myString = null;
string lowerCaseString = myString.ToLower();
Понятно, что вы выбрали исключение NullReferenceException, потому что я пытаюсь получить доступ к методу экземпляра ToLower() для ссылки, которая не существует, поэтому исключение Null Reference (т.е. есть вещь в стеке, но ничего в куче).
При выполнении NULL строк concat операций исключение будет означать, что тонны дополнительного защитного кода NULL проверяют при работе со строками, которые раздражают. Извините, но я согласен с тем, как это делает С#.NET. Разве Java не делает то же самое?
Если вы хотите проверить, содержит ли строка значение, используйте String.IsNullOrEmpty(myString);
или String.IsNullOrWhitespace(myString);
(только в .NET 4.0)
Ответ 7
На самом деле это то, как строки представлены... ничего плохого нет.
null используется как символ завершения.
Например:
string a: "blahblah [null]"
Таким образом, все, что читает строка, знает, что нужно остановить с нулевым значением.
поэтому, когда вы создаете такую строку:
строка b: "[null]"
это совершенно верно.
Теперь перед символом нет символов. поэтому, когда ваша программа начинает читать строку, она встречает нуль (отлично действует) и останавливается... таким образом... пустая строка!!