Мне просто интересно мнение людей. При использовании типов, допускающих значение NULL, в C# наилучший способ проверки наличия NULL:
bool isNull = (i == null);
или же
bool isNull = !i.HasValue;
Также при присвоении ненулевого типа это:
long? i = 1;
long j = (long)i;
лучше чем:
long? i = 1;
long j = i.Value;





Я бы всегда использовал форму (i == null). Он выражает то, что вы делаете.
WRT второй вопрос, я думаю, что любая форма хороша. Однако я всегда сначала проверял его на значение null и принимал соответствующие меры - возможно, обертывал эту проверку и действие во вспомогательном методе (часто он просто устанавливает значение по умолчанию).
Они оба одинаковы, но я бы использовал предыдущую версию на обоих, поскольку она более распространена в языке: сравнение с нулевым значением и приведение к типу.
Обычно я склоняюсь к первому варианту в обоих сценариях, поскольку он более «примитивен», чем объектно-ориентированный (что было действительно тем, к чему мы стремились), но на самом деле это не имеет большого значения.
Я бы использовал это:
long? i = 1;
...some code...
long j = i ?? 0;
Это означает, что если я равно нулевой, то будет присвоен 0.
Проблема, с которой я столкнулся с этой формой, заключается в том, что не все разработчики сразу узнают, что происходит.
Очень круто - я не обнаружил ?? оператора или "дефолт" пока нет.
@Ed Swangren, профессиональные программисты .net должны знать, что такое нулевой оператор объединения. Точно так же, как я ожидал, что разработчик C знает операторы битового сдвига. Не пишите код, руководствуясь самым низким знаменателем программистов, которые чему-то не научились.
Я мог бы это сделать, но это зависит от того, является ли 0 приемлемым контрольным значением.
Преобразовывая null в 0, вы фактически скрываете исключение. Это может быть подходящим, это зависит от того, можете ли вы принять значение по умолчанию. Также следует ли вам использовать ?? Оператор на самом деле не входил в мой вопрос.
На практике я не использовал типы, допускающие значение NULL, но во втором случае я бы предложил использовать j.GetValueOrDefault (). Документация предполагает, что последний на самом деле вызовет InvalidOperationException в случае нулевого значения. В зависимости от внутренней реализации оператора явного приведения long ?, первый тоже может. Я бы придерживался GetValueOrDefault и соответствующим образом относился к случаю null / default.
Используйте формы, специально разработанные для вас командой C#. Если кто-то возражает, скажите им, что Андерс сказал, что все в порядке.
Я легкомысленно говорю о том, что для интеграции типов, допускающих значение NULL, в C# было проделано много работы, чтобы дать вам хороший опыт программирования.
Обратите внимание, что с точки зрения производительности обе формы компилируются в один и тот же IL, то есть:
int? i = 1;
bool isINull = i == null;
int j = (int)i;
Заканчивается так после того, как компилятор C# добрался до него:
int? i = 1;
bool isINull = !i.HasValue;
int j = i.Value;
Я предпочитаю использовать первый для обоих, потому что, поскольку он нуждается в поддержке на более позднем этапе его жизненного цикла, кажется, что легче понять, каковы намерения исходного автора.
Открыл Reflector. HasValue - это поиск по логическому флагу, который устанавливается при изменении значения. Таким образом, с точки зрения циклов поиск будет быстрее, чем сравнение.
public Nullable(T value)
{
this.value = value;
this.hasValue = true;
}
private bool hasValue;
internal T value;
public bool HasValue
{
get
{
return this.hasValue;
}
}
Вы проверили, к чему сводится сравнение? Я был бы удивлен, если бы синтаксический сахар закончился чем-то другим, кроме вызова HasValue.
кроме того, если вы хотите назначить значение по умолчанию для этого типа значения (которое может быть или не быть 0), вы можете использовать long j = i ?? по умолчанию (длинный);