Глюки при использовании Nullable <T> в C# 4

Я только что начал писать на компоненте, где я нашел, что могло бы быть полезно объявить некоторые nullable свойства, вместо того, чтобы позволить им обратиться к значениям по умолчанию. Однако я понял, что прежде никогда не использовал non-nullable-type? синтаксис или Nullable<T> введите прежде, таким образом, существуют, вероятно, некоторые глюки, это скоро выскочит и укусит меня. Так...

  • Каковы самые большие глюки при использовании Nullable<T> и стенография ? синтаксис?

  • Как я работаю вокруг них?

  • Каковы самые большие преимущества / новые возможности, которые сделаны доступными для меня, когда я начинаю использовать их?

10
задан Tomas Aschan 19 July 2010 в 22:09
поделиться

8 ответов

Распространенная проблема - это попытка присвоения переменной, допускающей значение NULL, с помощью условного выражения, как показано ниже:

bool useDefault = true;
int defaultValue = 50;
int? y = useDefault ? defaultValue : null; 

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

Type of conditional expression cannot be determined because there is no
implicit conversion between 'int' and '<null>'

] Решение: добавьте приведение к одному или обоим возможным результатам:

int? y = useDefault ? defaultValue : (int?)null; 

Реже встречается: обычно можно с уверенностью предположить, что для целых чисел a <= 5 и ! (A> 5 ) эквивалентны. Это предположение неверно для целых чисел, допускающих значение NULL.

int? x = null;
Console.WriteLine(x <= 5);
Console.WriteLine(!(x > 5));

Результат:

False
True

Решение: обрабатывать нулевой регистр отдельно.


Вот еще один небольшой вариант вышеупомянутого:

int? y = null;
int? z = null;
Console.WriteLine(y == z);
Console.WriteLine(y <= z);

Вывод:

True
False

Итак, y равно z , но не меньше или равно от до z .

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

18
ответ дан 3 December 2019 в 14:42
поделиться

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

То есть, нулевое значение не является «другим» - оно означает неизвестное или неисчислимое в настоящее время, или что при других значениях в этом объекте / записи, это не имеет смысла, чтобы быть значением. Ваша ситуация выглядит так, как будто она действительна - пользовательские настройки могут быть нулевыми, а фактические значения будут

actualValue = userValue ?? defaultValue;

?? - это нулевой оператор объединения - приведенное выше эквивалентно следующему:

actualValue = userValue.HasValue ? userValue : defaultValue;

или

actualValue = (userValue != null) ? userValue : defaultValue;

Я вижу, что люди чаще всего поддаются искушению, используя bool? в качестве флага трех государств. Это не имеет смысла, потому что в true / false / ??? нет третьей возможности. Другим, читающим ваш код, придется копаться в комментариях (в лучшем случае), чтобы выяснить, что true означает использование синего текста, false означает красный текст, а null означает зеленый текст. Используйте для этого перечисления.

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

1
ответ дан 3 December 2019 в 14:42
поделиться

Nullable - это особый тип значения. Это может помочь, если вы поймете, как это на самом деле работает. В этом есть несколько тонких моментов, которые не сразу очевидны. Я писал о здесь .

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

1
ответ дан 3 December 2019 в 14:42
поделиться

В настоящее время я не использую 4.0, но в 2.0 у меня есть проблема, что, как и у большинства Generics, int? не может быть легко десериализован. Возможно, 4.0 умнее с Reflection, но стандартные утилиты XML-сериализатора не могут его прочитать. Это довольно неприятно.

0
ответ дан 3 December 2019 в 14:42
поделиться

Обнуляемые типы немного необычны; они (строго говоря) не являются ни значениями, ни ссылочными типами, а являются чем-то странным между ними. Упаковка / распаковка и typeof , в частности, имеют особые правила, поэтому результаты менее неожиданные.

Для получения подробной информации я рекомендую книгу Джона Скита C # in Depth . Если у вас его еще нет, вы должны это сделать. :)

1
ответ дан 3 December 2019 в 14:42
поделиться

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

вы можете сделать

 myvar = nullablevar ?? defaultvalue; //will set defaultvalue if nullablevar  is null

и многое другое, это не ново для c# 4

прочитайте это для дополнительной информации

1
ответ дан 3 December 2019 в 14:42
поделиться

Люди часто удивляются тому, что не существует такой вещи, как упакованный тип значения, допускающий значение NULL . Если вы скажете:

int? x = 123;
int? y = null;
int z = 456;
object xx = x;
object yy = y;
object zz = z;

, вы можете подумать, что, поскольку zz содержит упакованное целое число, то xx и yy содержат упакованные целые числа, допускающие значение NULL. Они не. xx содержит заключенное в рамку int. yy имеет значение null.

10
ответ дан 3 December 2019 в 14:42
поделиться

Бессознательная установка значения по умолчанию при использовании nullable. Я видел это несколько раз. Например,

int? localVar = 0;
// do something ..
if (localVar.HasValue)
   _myMemberValue = localVar.Value;

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

-- Отредактировано, чтобы добавить больше комментариев ----

Забыл упомянуть. Одним из основных преимуществ, которое я видел, является использование поля для представления Nullable поля в базе данных. Оно также генерируется автоматически, если вы используете Linq и EF. Но традиционно до появления Nullable, это ручная работа и склонность к ошибкам для обработки обновления поля и принятия решения о том, когда установить его со значением или в null.

0
ответ дан 3 December 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: