Почему значение по умолчанию типа строки null вместо пустой строки?



это очень раздражает, чтобы проверить все мои строки null прежде чем я смогу безопасно применять такие методы, как ToUpper(),StartWith() etc...



, если значение по умолчанию string если бы пустая строка, мне не пришлось бы тестировать, и я бы чувствовал, что она более согласуется с другими типами значений, такими как int или double например.
Дополнительно Nullable<String> имело бы смысл.



так почему же дизайнеры C# решили использовать null Как значение по умолчанию струны?



Примечание: это относится к этот вопрос, но больше сосредоточен на том, почему, а не что с ним делать.

959   14  

14 ответов:

почему значение по умолчанию типа строки null вместо пустого струна?

, потому что string Это ссылка типа и значение по умолчанию для всех ссылочных типов составляет null.

это довольно раздражает, чтобы проверить все мои строки для null, прежде чем я могу безопасно применять такие методы, как ToUpper (), StartWith() и т. д...

, что согласуется с поведением ссылочных типов. Прежде чем ссылаться на них члены экземпляра, следует поставить галочку на место для нулевой ссылки.

если бы значение по умолчанию string было пустой строкой, я бы не стал чтобы проверить, и я бы чувствовал, что это более согласуется с другими например, такие типы значений, как int или double.

присвоение значения по умолчанию определенному ссылочному типу, отличному от null бы непоследовательны.

дополнительно Nullable<String> сделали бы чувство.

Nullable<T> работает с типами значений. Следует отметить тот факт, что Nullable не был представлен на оригинальной платформе.NET так что было бы много сломанного кода, если бы они изменили это правило.(вежливость @jcolebrand)

Хабиб прав-потому что string является ссылочным типом.

но что еще более важно, вы не нужно проверить null каждый раз, когда вы используете его. Вы, наверное, должны бросить ArgumentNullException Если кто-то передает вашу функцию a null справочники, хотя.

вот в чем дело -- каркас будет бросать NullReferenceException для вас в любом случае, если вы пытались позвонить .ToUpper() на строку. Помните, что этот случай все еще может произойти, даже если вы проверяете свои аргументы null поскольку любое свойство или метод на объектах, переданных в вашу функцию в качестве параметров, может оцениваться в null.

как говорится, проверка пустых строк или нулей-это обычная вещь, поэтому они предоставляют String.IsNullOrEmpty() и String.IsNullOrWhiteSpace() только для этой цели.

вы могли бы написать метод расширения (для чего это стоит):

public static string EmptyNull(this string str)
{
    return str ?? "";
}

теперь это безопасно работает:

string str = null;
string upper = str.EmptyNull().ToUpper();

пустые строки и нули принципиально разные. Null-это отсутствие значения, а пустая строка-это пустое значение.

язык программирования, делающий предположения о" значении " переменной, в данном случае пустой строки, будет так же хорош, как инициализация строки с любым другим значением, которое не вызовет проблему нулевой ссылки.

кроме того, если вы передадите дескриптор этой строковой переменной в другие части приложения, то этот код будет у вас нет способов проверить, намеренно ли вы передали пустое значение или забыли заполнить значение этой переменной.

еще один случай, когда это было бы проблемой, когда строка является возвращаемым значением из некоторой функции. Поскольку string является ссылочным типом и технически может иметь значение как null, так и empty, поэтому функция также может технически возвращать null или empty (нет ничего, чтобы остановить ее от этого). Теперь, поскольку есть 2 понятия "отсутствие значения", т. е. пустая строка и null, весь код, который потребляет эту функцию, должен будет выполнить 2 проверки. Один пустой, а другой-для нулевого.

короче говоря, всегда хорошо иметь только 1 представление для одного состояния. Для более широкого обсуждения пустых и нулевых значений см. ссылки ниже.

https://softwareengineering.stackexchange.com/questions/32578/sql-empty-string-vs-null-value

NULL vs пустой, когда работа с пользовательским вводом

вы также можете (начиная с VS2015 и нового компилятора) использовать следующее

string myString = null;
string result = myString?.ToUpper();

результат строки будет null.

потому что строковая переменная-это ссылка, а не экземпляр.

инициализация его пустым по умолчанию было бы возможно, но это ввело бы много несоответствий по всей плате.

Почему разработчики C# решили использовать null в качестве значения по умолчанию струны?

потому что строки ссылка типа, ссылочные типы имеют значение по умолчанию null. Переменные ссылочных типов хранят ссылки на фактические данные.

давайте использовать default ключевое слово для данного случая;

string str = default(string); 

str это string, поэтому ссылка типа, так значение по умолчанию:null.

int str = (default)(int);

str это int, поэтому тип значения, поэтому значение по умолчанию:zero.

основная причина / проблема заключается в том, что разработчики спецификации CLS (которая определяет, как языки взаимодействуют с .net) не определили средство, с помощью которого члены класса могли бы указать, что они должны вызываться напрямую, а не через callvirt, без вызывающего объекта, выполняющего проверку нулевой ссылки; также он не предоставлял средства определения структур, которые не подлежали бы "нормальному" боксу.

если бы спецификация CLS определила такое средство, то это было бы для .net возможно последовательно следовать примеру, установленному общей объектной моделью (COM), в которой ссылка на нулевую строку считалась семантически эквивалентной пустой строке, а для других определяемых пользователем неизменяемых типов классов, которые должны иметь семантику значений, аналогично определять значения по умолчанию. По сути, то, что произойдет, будет для каждого члена String, например,Length должно быть написано как что-то вроде [InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} }. Этот подход предложил бы очень хорошую семантику для вещей, которые должны вести себя как значения, но из-за проблем с реализацией должны храниться в куче. Самая большая трудность с этим подходом заключается в том, что семантика преобразования между такими типами и Object может стать немного мутным.

альтернативным подходом было бы разрешить определение специальных типов структур, которые не наследуются от Object но вместо этого были пользовательские операции бокса и распаковки (которые будут преобразовываться в / из другого класса тип.) При таком подходе был бы класс типа NullableString который ведет себя как string делает сейчас, и пользовательский коробочный тип структуры String, который будет содержать одно частное поле Value типа String. Попытка преобразовать String to NullableString или Object вернутся Value если не-null, или String.Empty если значение null. Попытка бросить в String, а не-null ссылка на NullableString экземпляр будет хранить ссылку в Value (возможно хранение null, если длина была равна нулю); литье любая другая ссылка вызовет исключение.

хотя строки должны храниться в куче, концептуально нет причин, почему они не должны вести как типы значений, которые имеют ненулевое значение по умолчанию. Если бы они хранились как "нормальная" структура, содержащая ссылку, было бы эффективно для кода, который использовал их как тип "строка", но добавил бы дополнительный уровень косвенности и неэффективности при приведении к "объекту". Пока я не предвидите, что .net добавит любую из вышеперечисленных функций на этой поздней дате, возможно, дизайнеры будущих фреймворков могут рассмотреть их включение.

, если значение по умолчанию string были бы пустые строки, Мне бы не пришлось тестировать

неправильно! Изменение значения по умолчанию не меняет того факта, что это ссылочный тип, и кто-то все еще может явно set ссылки null.

дополнительно Nullable<String> имело бы смысл.

настоящий момент. Было бы разумнее не допускать null для любых ссылочных типов, а Nullable<TheRefType> для данного объекта.

так почему же дизайнеры C# решили использовать null как значение по умолчанию строк?

согласованность с другими ссылочными типами. Теперь, зачем позволять null в ссылочных типах вообще? Вероятно, так, что он чувствует себя как C, хотя это сомнительное дизайнерское решение на языке, который также обеспечивает Nullable.

возможно, если бы вы использовали ?? оператор при назначении строковой переменной, это может помочь вам.

string str = SomeMethodThatReturnsaString() ?? "";
// if SomeMethodThatReturnsaString() returns a null value, "" is assigned to str.

строка-это неизменяемый объект, который означает, что при задании значения старое значение не стирается из памяти, а остается в старом месте, а новое значение помещается в новое место. Так что если значение по умолчанию String a был String.Empty он будет тратить String.Empty блок в памяти, когда ему было присвоено первое значение.

хотя это кажется незначительным, это может превратиться в проблему при инициализации большого массива строк со значениями по умолчанию String.Empty. Конечно, вы могли бы всегда используйте изменяемый StringBuilder класс, если это будет проблемой.

поскольку string является ссылочным типом, а значение по умолчанию для ссылочного типа равно null.

может быть string ключевое слово смутило вас, так как оно выглядит точно так же, как и любое другое тип значения объявление, но на самом деле это псевдоним для System.String Как поясняется в этот вопрос.
Кроме того, темно-синий цвет в Visual Studio и строчная первая буква могут ввести в заблуждение, думая, что это struct.

типы с нулевым значением не появлялись до 2.0.

Если бы nullable типы были сделаны в начале языка, то строка была бы не nullable и string? это было бы ничтожно. Но они не могли сделать это для обратной совместимости.

многие люди говорят о ref-типе или не ref-типе, но string является необычным классом, и решения были бы найдены, чтобы сделать это возможным.

Comments

    Ничего не найдено.