Инициализация строки по умолчанию: NULL или Пусто?

Я всегда инициализировал свои строки как NULL, думая, что NULL означает отсутствие значения, а "" или String.Empty является допустимым значением. В последнее время я видел больше примеров кода, где String.Empty считается значением по умолчанию или не представляет значения. Это кажется мне странным, с недавно добавленными обнуляемыми типами в C# кажется, что мы делаем шаги назад со строками, не используя NULL для представления 'No Value'.

Что вы используете в качестве инициализатора по умолчанию и почему?

Изменить: основываясь на ответах, я продолжу свои дальнейшие мысли

  1. Как избежать обработки ошибок Если значение не должно быть нулевым, почему оно установлено в NULL на первом месте? Возможно, было бы лучше определить ошибку в том месте, где она возникает, а не скрывать ее до конца вашей кодовой базы?

  2. Как избежать нулевых проверок Если вы устали выполнять нулевые проверки в коде, не лучше ли абстрагировать нулевые проверки? Возможно обернуть (или расширить!) Строковые методы, чтобы сделать их NULL безопасный? Что произойдет, если вы постоянно используете String.Empty и случается, что ноль работает, это путь в вашу систему, вы начинаете добавлять NULL проверяет в любом случае?

Я не могу не вернуться к мнению, что это лень. Любой администратор базы данных дал бы вам девять глупых способов, если бы вы использовали '' вместо null в его базе данных. Я думаю, что те же самые принципы применяются в программировании, и должен быть кто-то, кто ударит тех, кто использует голову String.Empty скорее, чем NULL не представлять никакой ценности.

Смежные вопросы

17 ответов

Решение

+1 за различие между "пустым" и NULL. Я согласен, что "пусто" должно означать "допустимо, но пусто", а "NULL" должно означать "недействительно".

Поэтому я бы ответил на ваш вопрос так:

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

NULL, если это ошибка, если следующий код не устанавливает значение явно.

По данным MSDN:

Инициализируя строки с помощью Empty значение вместо nullВы можете уменьшить шансы NullReferenceException происходит.

Всегда использую IsNullOrEmpty() тем не менее, это хорошая практика.

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

Я вижу это много:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else
{
  name = "bar";
}

return name;

Не инициализация к нулю была бы столь же эффективной. Кроме того, чаще всего вы хотите, чтобы значение было присвоено. Инициализируя значение null, вы потенциально можете пропустить пути кода, которые не присваивают значение. Вот так:

string name = null; // or String.Empty
if (condition)
{
  name = "foo";
}
else if (othercondition)
{
  name = "bar";
}

return name; //returns null when condition and othercondition are false

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

Matthijs

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

if (s == "value")

У меня плохое предчувствие. Почему в этом методе есть строковый литерал? Что настройки s? Знает ли он, что логика зависит от значения строки? Знает ли он, что он должен быть в нижнем регистре, чтобы работать? Должен ли я исправить это, изменив его на использование String.Compare? Должен ли я создавать Enum и разбор в это?

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

Зная это, я не моргаю, когда вижу что-то подобное в нашей базе кода:

string msg = Validate(item);
if (msg != null)
{
   DisplayErrorMessage(msg);
   return;
}

я знаю это Validate никогда не вернется String.Emptyпотому что мы пишем лучший код, чем это.

Конечно, остальной мир не работает так. Когда ваша программа имеет дело с пользовательским вводом, базами данных, файлами и т. Д., Вы должны учитывать другие принципы. Там задача вашего кода - навести порядок в хаосе. Часть этого порядка знает, когда пустая строка должна означать String.Empty и когда это должно означать null,

(Просто чтобы убедиться, что я не говорил из своей задницы, я просто искал в нашей кодовой базе `String.IsNullOrEmpty'. Все 54 его вхождения находятся в методах, которые обрабатывают пользовательский ввод, возвращают значения из скриптов Python, проверяют значения, полученные из внешние API и т. д.)

На самом деле это зияющая дыра в языке C#. Нет способа определить строку, которая не может быть нулевой. Это приводит к таким простым проблемам, как та, которую вы описываете, что заставляет программистов принимать решение, которое им не нужно принимать, поскольку во многих случаях NULL и String.Empty означают одно и то же. Это, в свою очередь, может позже заставить других программистов работать с NULL и String.Empty, что раздражает.

Большая проблема заключается в том, что базы данных позволяют вам определять поля, которые отображаются в строку C#, но поля базы данных могут быть определены как NOT NULL. Таким образом, нет никакого способа точно представить, скажем, поле varchar( 100) NOT NULL в SQL Server, используя тип C#.

Другие языки, такие как SpeC#, разрешают это.

На мой взгляд, неспособность C# определить строку, которая не допускает null, так же плоха, как и его предыдущая неспособность определить int, которая допускает null.

Чтобы полностью ответить на ваш вопрос: я всегда использую пустую строку для инициализации по умолчанию, потому что она больше похожа на работу типов данных базы данных. (Редактировать: это утверждение было очень непонятным. Оно должно гласить: "Я использую пустую строку для инициализации по умолчанию, когда NULL является избыточным состоянием, во многом таким же образом я настраивал столбец базы данных как NOT NULL, если NULL был бы избыточным состоянием. многие из моих столбцов БД установлены как NOT NULL, поэтому, когда я перенесу их в строку C#, строка будет пустой или будет иметь значение, но никогда не будет NULL. Другими словами, я только инициализирую строку в NULL если значение null имеет значение, отличное от значения String.Empty, и я нахожу, что этот случай меньше обычного (но люди здесь привели законные примеры этого случая).")

Это зависит.

Нужно ли вам знать, если значение отсутствует (возможно ли его не определить)?

Является ли пустая строка допустимым значением для использования этой строки?

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

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

Кажется, что это особый случай http://en.wikipedia.org/wiki/Null_Object_pattern

Я либо устанавливаю его на "", либо на ноль - я всегда проверяю с помощью String.IsNullOrEmpty, так что либо все в порядке.

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

Я всегда объявляю строку с помощью string.empty;

Я всегда инициализирую их как NULL,

Я всегда использую string.IsNullOrEmpty(someString) проверить это значение.

Просто.

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

Пустая строка - это значение (фрагмент текста, который, кстати, не содержит букв). Нуль означает отсутствие значения.

Я инициализирую переменные равными нулю, когда хочу указать, что они не указывают на фактические значения или не содержат их - когда намерение не для значения.

Нуль следует использовать только в тех случаях, когда значение является необязательным. Если значение не является обязательным (например, "Имя" или "Адрес"), тогда значение никогда не должно быть нулевым. Это относится к базам данных, а также к POCO и пользовательскому интерфейсу. Нуль означает "это значение не является обязательным и в настоящее время отсутствует".

Если ваше поле не является обязательным, вы должны инициализировать его как пустую строку. Чтобы инициализировать его как null, вы поместите ваш объект в недопустимое состояние (недопустимое вашей собственной моделью данных).

Лично я предпочел бы, чтобы строки не обнулялись по умолчанию, а вместо этого только обнулялись, если мы объявляем "строку?". Хотя, возможно, это не осуществимо или логично на более глубоком уровне; Точно сказать не могу.

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

Я устанавливаю строку на null только тогда, когда мне нужно знать, была ли она установлена ​​или нет, и где пустая строка является чем-то допустимым для установки. На практике я нахожу такие ситуации редкими.

Повторяя ответ Tomalak, помните, что когда вы присваиваете строковую переменную начальному значению null, ваша переменная больше не является строковым объектом; То же самое с любым объектом в C#. Таким образом, если вы пытаетесь получить доступ к каким-либо методам или свойствам для вашей переменной и предполагаете, что это строковый объект, вы получите исключение NullReferenceException.

Строки не являются типами значений и никогда не будут;-)

Я думаю, что нет никаких причин не использовать null для неназначенного (или в этом месте в потоке программы не происходит) значения. Если вы хотите различить, есть == ноль. Если вы просто хотите проверить определенное значение и не заботитесь о том, является ли оно нулевым или чем-то другим, String.Equals("XXX",MyStringVar) работает отлично.

Другие вопросы по тегам