41 votes

L'opérateur C# || ne fonctionne pas avec les booléens nullables

J'ai le morceau de code suivant dans mon LINQ :

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

Notez que Shipped, Ordered et Processed sont tous des champs booléens annulables.

Je reçois le message suivant :

L'opérateur || ne peut pas être appliqué aux opérandes de type 'bool?' et 'bool ?

Je ne sais pas comment résoudre ce problème car, oui, il doit s'agir de booléens nuls et je dois utiliser l'opérateur OU (||).

103voto

Eric Lippert Points 300275

Prenez du recul et réfléchissez au problème. Vous voulez une collection de widgets où le widget a été commandé, ou le widget a été expédié, ou le widget a été traité.

Il y a quatre états possibles pour votre connaissance de "ordonné" :

  • ce widget a été commandé et je sais que (vrai)
  • ce widget n'a pas été commandé et je sais que (faux)
  • ce widget a été commandé mais je ne sais pas si (null)
  • ce widget n'a pas été commandé mais je ne sais pas si (null)

Il y a quatre états mais seulement trois valeurs possibles. Par conséquent, si "ordered" est dans l'état nul vous ne savez pas s'il doit être inclus dans les résultats de la requête ou non .

Le compilateur ne le sait pas non plus.

Il n'y a tout simplement pas assez d'informations disponibles pour que le compilateur puisse vous donner une requête ayant la sémantique que vous souhaitez. Le compilateur ne va pas faire une supposition et éventuellement vous donner de mauvais résultats ; le compilateur va vous dire qu'il n'y a pas assez d'informations ici et que vous devez faire plus de travail pour rendre la requête non ambiguë.

Ce que vous devez faire, c'est dire Que faire dans le cas où vous ne connaissez pas la réponse ? . La requête "tous les gadgets qui ont été commandés, expédiés ou traités" est impossible car certains gadgets nous ne savons pas s'ils ont été commandés, expédiés ou traités, et nous ne savons donc pas s'il faut les inclure ou non. Mais la requête "tous les gadgets que je sais ont été commandés, ou que je sais ont été expédiés, ou que je sais ont été traitées" est une requête à laquelle le compilateur peut donner un sens :

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

Cela signifie que "si je ne sais pas si elle a été expédiée, etc., je suppose qu'elle ne l'a pas été".

Vous pourriez plutôt vouloir la requête "tous les widgets qui étaient certainement, ou auraient pu être expédié, commandé ou traité :

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

Le compilateur ne va pas deviner de quel côté vous voulez vous tromper quand il n'y a pas assez d'informations pour donner des résultats précis ; le compilateur peut se tromper et nous ne sommes pas là pour prendre des décisions à votre place. C'est à vous de prendre cette décision.

39voto

Essayez

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

18voto

adelphus Points 1463

Vous devez vous assurer que l'expression n'est jamais null . Vous pourriez le faire avec l'opérateur null-coalesce, ?? :

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

5voto

sll Points 30638
where ((tf.Shipped.HasValue && tf.Shipped.Value)
       || (tf.Ordered.HasValue && tf.Ordered.Value)
       || (tf.Processed.HasValue && tf.Processed.Value))

2voto

SandRock Points 1990

Vous pouvez également utiliser le GetValueOrDefault dans votre cas spécifique.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X