C # ||оператор не работает с булевыми значениями - PullRequest
41 голосов
/ 27 января 2012

У меня есть следующий фрагмент кода в моем LINQ:

    where (tf.Shipped || tf.Ordered || tf.Processed)

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

Я получаю следующее сообщение:

Оператор || нельзя применять к операндам типа 'bool?' и "bool?"

Не уверен, как решить это как да, они должны быть логическими значениями, допускающими обнуляемость, и мне нужно использовать ИЛИ (||).

Ответы [ 6 ]

103 голосов
/ 27 января 2012

Сделайте шаг назад и подумайте о проблеме. Вы хотите коллекцию виджетов, где виджет был заказан, или виджет был отправлен, или виджет был обработан.

Существует четыре возможных состояния вашего знания "заказанного":

  • этот виджет был заказан и я знаю, что (true)
  • этот виджет не был заказан и я знаю, что (false)
  • этот виджет был заказан но я не знаю, что (null)
  • этот виджет не был заказан , но я не знаю, что (null)

Существует четыре состояния, но возможны только три значения. Поэтому, если «заказано» в нулевом состоянии , вы не знаете, должно ли оно быть включено в результаты запроса или нет .

Компилятор тоже этого не знает.

Для компилятора просто недостаточно информации, чтобы дать вам запрос с нужной вам семантикой. Компилятор не собирается делать предположения и, возможно, даст вам плохие результаты; компилятор скажет вам, что здесь недостаточно информации, и вам нужно проделать дополнительную работу, чтобы сделать запрос однозначным.

Что вам нужно сделать, это сказать , что делать в том случае, если вы не знаете ответ . Запрос "все виджеты, которые были заказаны, отправлены или обработаны" невозможен, потому что некоторые виджеты мы не знаем , были ли они заказаны, отправлены или обработаны, и поэтому мы не знаем, включать ли их или нет. Но запрос "все виджеты , которые, как я знаю, , были заказаны, или , которые, как я знаю, были отправлены, или , которые, как я знаю, были обработаны", - это запрос, который Компилятор может иметь смысл:

where (tf.Shipped ?? false) || (tf.Ordered ?? false) || (tf.Processed ?? false)

Это означает, что «если я не знаю, было ли оно отправлено и т. Д., Предположим, что оно не было».

Вместо этого вам может потребоваться запрос "все виджеты, которые определенно были или могли быть отправлены, заказаны или обработаны:

where (tf.Shipped ?? true) || (tf.Ordered ?? true) || (tf.Processed ?? true)

Компилятор не собирается угадывать, на какой стороне вы хотите ошибиться, когда недостаточно информации для получения точных результатов; компилятор может ошибиться, и мы не принимаем решения от вашего имени. Вам придется принять это решение.

39 голосов
/ 27 января 2012

Попробуйте

 where (tf.Shipped == true || tf.Ordered  == true || tf.Processed == true )
18 голосов
/ 27 января 2012

Вы должны убедиться, что выражение никогда не будет null. Вы можете сделать это с помощью оператора null-coalesce, ??:

where ((tf.Shipped ?? false) || (tf.Ordered ?? false) || (tf.Processed ?? false))
5 голосов
/ 27 января 2012
where ((tf.Shipped.HasValue && tf.Shipped.Value)
       || (tf.Ordered.HasValue && tf.Ordered.Value)
       || (tf.Processed.HasValue && tf.Processed.Value))
2 голосов
/ 02 февраля 2012

Вы также можете использовать GetValueOrDefault в вашем конкретном случае.

where (tf.Shipped.GetValueOrDefault()
    || tf.Ordered.GetValueOrDefault()
    || tf.Processed.GetValueOrDefault() )
1 голос
/ 27 января 2012
where ((tf.Shipped.HasValue && tf.Shipped.Value) 
   || (tf.Ordered.HasValue && tf.Ordered.Value) 
   || (tf.Processed.HasValue && tf.Processed.Value)) 
...