С# добавление строки + 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]" это совершенно верно.

Теперь перед символом нет символов. поэтому, когда ваша программа начинает читать строку, она встречает нуль (отлично действует) и останавливается... таким образом... пустая строка!!