Почему я не должен всегда использовать обнуляемые типы в C # - PullRequest
35 голосов
/ 06 мая 2009

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

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

Есть ли «значительный» удар по производительности при выборе типа данных, допускающих значение NULL, по сравнению с равным ему значением NULL?

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

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

Спасибо за ваше время,

Ответы [ 7 ]

46 голосов
/ 06 мая 2009

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

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

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

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

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

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

9 голосов
/ 06 мая 2009

Поскольку неудобно всегда проверять, имеет ли обнуляемый тип 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();
3 голосов
/ 06 мая 2009

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

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

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

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

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

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

3 голосов
/ 06 мая 2009

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

1 голос
/ 06 мая 2009

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

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

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

См. Также вопрос, Почему в C # и java присутствует «ноль»?

0 голосов
/ 24 января 2015

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

0 голосов
/ 06 мая 2009

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

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

...