Почему я не должен всегда использовать типы с нулевым значением в C#

StackOverflow https://stackoverflow.com/questions/830592

  •  06-07-2019
  •  | 
  •  

Вопрос

Я искал какое-нибудь хорошее руководство по этому поводу с тех пор, как концепция была представлена в .net 2.0.

Зачем мне вообще хотеть использовать ненулевые типы данных в c #?(Лучший вопрос заключается в том, почему бы мне не выбрать типы с нулевым значением по умолчанию и использовать ненулевые типы только тогда, когда это явно имеет смысл.)

Есть ли "значительное" снижение производительности при выборе обнуляемого типа данных вместо его ненулевого однорангового узла?

Я предпочитаю сверять свои значения с null вместо Guid.empty, string.empty, DateTime.MinValue,<= 0 и т.д., а также для работы с обнуляемыми типами в целом.И единственная причина, по которой я не выбираю типы с нулевым значением чаще, - это ощущение зуда в затылке, которое заставляет меня чувствовать, что это нечто большее, чем обратная совместимость, которая заставляет этот дополнительный символ '?' явно разрешать нулевое значение.

Есть ли кто-нибудь, кто всегда (почти всегда) выбирает обнуляемые типы, а не ненулевые типы?

Спасибо, что уделили мне время,

Это было полезно?

Решение

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

List<int> list = new List<int>()
int c = list.Count;

Это всегда действительный.Нет никакого возможного способа, которым c может быть неинициализированным.Если бы это было превращено в int?, вы бы фактически сообщали читателям кода: "это значение может быть null.Обязательно проверьте, прежде чем использовать его ".Но мы знаем, что этого никогда не может произойти, так почему бы не включить эту гарантию в код?

Вы абсолютно правы в тех случаях, когда значение является необязательным.Если у нас есть функция, которая может возвращать, а может и не возвращать строку, то верните null .Не возвращайте строку.Empty().Не возвращайте "магические значения".

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

Если вы можете конкретно гарантировать, что это значение всегда будет действительным, то зачем выбрасывать эту информацию?Это то, что вы делаете, присваивая ему нулевой тип.Теперь значение может существовать, а может и не существовать, и любому, кто использует это значение, придется обрабатывать оба случая.Но вы знаете, что, во-первых, возможен только один из этих случаев.Так что сделайте одолжение пользователям вашего кода и отразите этот факт в вашем коде.Тогда любые пользователи вашего кода могут полагаться на то, что значение является допустимым, и им нужно обрабатывать только один случай, а не два.

Другие советы

Потому что неудобно всегда проверять, является ли нулевой тип null.

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

// nice and simple, this will always work
int a = myInt;

// compiler won't let you do this
int b = myNullableInt;

// compiler allows these, but causes runtime error if myNullableInt is null
int c = (int)myNullableInt;
int d = myNullableInt.Value;    

// instead you need to do something like these, cumbersome and less readable
int e = myNullableInt ?? defaultValue;
int f = myNullableInt.HasValue ? myNullableInt : GetValueFromSomewhere();

Я думаю, разработчики языка считают, что "ссылочные типы, по умолчанию обнуляемые", были ошибкой, и что ненулевое значение является единственным разумным значением по умолчанию, и вам следует выбрать значение nullness.(Именно так обстоит дело во многих современных функциональных языках.) "null" - это обычно куча неприятностей.

Кажется, у вас есть 2 разных вопроса...

Зачем мне вообще хотеть использовать ненулевые типы данных в C #?

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

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

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

Конечно, когда ваши данные поступают из любого места, которое не является вашей программой, тогда все ставки отменяются.Лучший пример - из базы данных.Поля базы данных могут быть null, поэтому вы хотели бы, чтобы ваша программная переменная имитировала это значение, а не просто создавала "волшебное" значение (т. е.-1, 0 или что-то еще), что "представляет" null.Вы делаете это с обнуляемыми типами.

Хотя значения null могут быть удобны для использования как "еще не инициализированные" или "не указанные" значения, они усложняют код, главным образом потому, что вы перегружаете значение null а также переменная (number-or-null по сравнению спросто-число).

Нулевые значения предпочитают многие разработчики баз данных и программисты баз данных SQL, но с небольшим изменением подхода к проблеме вы можете отказаться от нулевых значений и фактически получить более простой и надежный код (например, не беспокоиться о NullReferenceExceptionы).

На самом деле существует большой спрос на оператор "T!", который делает любой ссылочный тип ненулевым, аналогично тому, как "T?" делает типы значений обнуляемыми, и Андерс Хейлсберг, изобретатель C #, пожалел, что не включил эту возможность.

Смотрите также вопрос, Почему “null” присутствует в C # и java?

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

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

Единственный раз, когда следует использовать тип с нулевым значением, это в том случае, когда определенное поле в таблице базы данных абсолютно требует, чтобы null было отправлено или получено приложением в какой-то момент.Даже в таком случае всегда следует пытаться найти способ обойти использование Nullable типа.Бул не всегда твой лучший друг.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top