Использование типов, допускающих значение NULL в C#

Мне просто интересно мнение людей. При использовании типов, допускающих значение 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;
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
0
12 409
8
Перейти к ответу Данный вопрос помечен как решенный

Ответы 8

Я бы всегда использовал форму (i == null). Он выражает то, что вы делаете.

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

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

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

Я бы использовал это:

long? i = 1;
...some code...
long j = i ?? 0;

Это означает, что если я равно нулевой, то будет присвоен 0.

кроме того, если вы хотите назначить значение по умолчанию для этого типа значения (которое может быть или не быть 0), вы можете использовать long j = i ?? по умолчанию (длинный);

Lloyd Cotten 03.11.2008 22:12

Проблема, с которой я столкнулся с этой формой, заключается в том, что не все разработчики сразу узнают, что происходит.

Ed S. 03.11.2008 22:55

Очень круто - я не обнаружил ?? оператора или "дефолт" пока нет.

Sam Schutte 03.11.2008 23:13

@Ed Swangren, профессиональные программисты .net должны знать, что такое нулевой оператор объединения. Точно так же, как я ожидал, что разработчик C знает операторы битового сдвига. Не пишите код, руководствуясь самым низким знаменателем программистов, которые чему-то не научились.

mmcdole 03.11.2008 23:47

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

mackenir 04.11.2008 11:19

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

Martin Brown 19.10.2010 19:29

На практике я не использовал типы, допускающие значение 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.

mackenir 04.11.2008 01:37

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