Явные типы, допускающие значение NULL, и где != null

При использовании новых функций явных ссылочных типов, допускающих значение NULL, в C# 8.0 (все типы должны быть явно объявлены как допускающие значение NULL, если они должны быть установлены в null https://docs.microsoft.com/en-us/dotnet/csharp/nullable-references ), как вы справляетесь со следующей ситуацией:

Скажем, у вас есть функция, которая возвращает IEnumerable из Something?

var result = aFunction()
         .Where(data => data != null)
         .Select(data => data.Id).ToList();

data.Id отображается как ошибка (у меня есть предупреждения об ошибках):

Явные типы, допускающие значение NULL, и где != null

потому что он может быть нулевым, даже если он проверяется, чтобы быть не нулевым с помощью Where. Я не хочу подавлять ошибку в этом случае, есть ли способ справиться с этим синтаксически?

вы задаете субъективный вопрос здесь. Что вы пробовали? Вы пробовали data.HasValue в предложении where и data.Value.Id в Select/Projection/Map?

Brett Caswell 17.05.2022 07:56

ссылочные типы, допускающие значение NULL, не имеют HasValue

Tim Rutter 17.05.2022 07:57

я не понимаю, почему это субъективно

Tim Rutter 17.05.2022 07:58

Я не получаю предупреждений, и в моем тестовом проекте все выглядит нормально (Visual Studio 2022, .Net 6, консольный проект)

D A 17.05.2022 07:59

это будет потому, что у вас не включено «nullable». это относительно новая функция, см. здесь: docs.microsoft.com/en-us/dotnet/csharp/nullable-references. Также нужны предупреждения, как ошибки, чтобы создать ошибку. Это устраняет риск исключений с нулевыми ссылками.

Tim Rutter 17.05.2022 08:00

Он у меня есть, и я очень хорошо об этом знаю. <Nullable>включить</Nullable>

D A 17.05.2022 08:03

Я думаю, что в этом конкретном случае вам нужно вручную сказать, что данные не равны нулю: Select(data => data!.Id) Я не думаю, что компилятор это понимает\

Bizhan 17.05.2022 08:03

Фраза «Как вы поступите в следующей ситуации» показалась мне субъективной, но, возможно, это спорно. Дайте мне секунду, чтобы просмотреть это утверждение об отсутствии HasValue для явно обнуляемого ссылочного типа в отношении этой функции. Я могу что-то неправильно понять.

Brett Caswell 17.05.2022 08:04

@Bizhan, который в основном подавляет предупреждение, но я думаю, что это ответ. Я не знал об этом! обозначение. Это синтаксически аккуратно.

Tim Rutter 17.05.2022 08:04

Вы можете попробовать aList.Where(data => data != null).OfType<Something>().Select(data => data.Id).ToList();

SomeBody 17.05.2022 08:06

попробуй var result = aList.Select(data => data?.Id).Where(id=>id.HasValue).ToList();

Mohammad Aghazadeh 17.05.2022 08:12

Это работает для меня... dotnetfiddle.net/ofj2AQ

Prasad Telkikar 17.05.2022 08:14

я обновил ответ, я упростил его из своего кода

Tim Rutter 17.05.2022 08:28

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

Brett Caswell 17.05.2022 08:40

примечание: data != nullна самом деле не означает, что data не null; вы можете создать тип, который действительно выдаст NRE в этом случае (т. е. data все еще может быть null); чтобы проверить «данные не являются нулевыми», не спрашивая «что это за тип? как он себя ведет?» вам действительно следует использовать тест data is not null (по крайней мере, в последних версиях C#; вы можете сделать то же самое в более старых версиях C#, но он более подробный)

Marc Gravell 17.05.2022 10:29

пример: Sharlab.io/…

Marc Gravell 17.05.2022 10:30
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
16
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Компилятор недостаточно «умен», чтобы определить, что аргумент Select() не может быть нулевым в этом случае, поскольку он выполняет только статический анализ кода. Для таких ситуаций ! нотация была введена с нулевыми ссылочными типами. Применение восклицательного знака к объекту говорит компилятору «заткнуться» в отношении предупреждений о допустимости значений NULL.

var result = aFunction()
         .Where(data => data != null)
         .Select(data => data!.Id).ToList();

Это означает, что компилятор не будет генерировать предупреждение о том, что data может быть нулевым. Это полезно во всех случаях, когда вы знаете, что значение не равно null, но компилятор (например, из-за сложности кода) не определяет это должным образом.

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

спасибо за ответ, я, вероятно, воспользуюсь этим, однако для абсолютной уверенности в том, что не будут получены исключения нулевых ссылок, использование OfType<Something> в приведенном выше примере, по-видимому, работает во всех случаях без исключений нулевых ссылок.

Tim Rutter 17.05.2022 08:42

Да, но это также добавляет сложности. Мой ответ указывает на общее использование восклицательного знака, поскольку он также может быть полезен вне запросов linq (например, с полями, допускающими значение NULL, которые, как вы знаете, не являются нулевыми в каком-либо методе).

PMF 17.05.2022 08:48

с этим фрагментом.. Я не думаю, что вы получите нулевую ссылку, Тим. Решение здесь заключается в устранении предупреждения статического анализа компилятора. Это предупреждение является ошибкой, потому что вы рассматриваете предупреждения как ошибки. и да, введение сложностей — с OfType — кажется необоснованным.

Brett Caswell 17.05.2022 08:50

кроме того, nullable-reference-types для языковой функции немного более актуален / ограничен для этого обсуждения (тогда ссылка в вопросе). docs.microsoft.com/en-us/dotnet/csharp/language-reference/…

Brett Caswell 17.05.2022 08:56

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