【问题标题】:C# || operator not working with nullable booleansC# ||运算符不使用可为空的布尔值
【发布时间】:2012-02-20 16:06:20
【问题描述】:

我的 LINQ 中有以下代码:

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

请注意,Shipped、Ordered 和 Processed 都是可为空的布尔字段

我收到以下消息:

操作员 ||不能应用于“bool”类型的操作数?和“布尔?”

不确定如何解决这个问题,它们需要是可为空的布尔值,我需要使用 OR (||)。

【问题讨论】:

  • @DoctorMick 大量使用。假设我有一份健康评估表,询问患者是否进行了前列腺检查。这不适用于女性。不是truefalse。这是null - 在这种情况下为 N/A。
  • 您期待什么?类似于与 SQL 的NULL 比较的结果?即当您的值为null时,是否应该将其简单地视为false
  • @DoctorMick 我记得在 nullables 之前,我们在名为 Troolean 的代码库中有一个类型。严肃而有用。
  • 如果所有人都是null,他的期望对我来说绝对不明显。
  • @Ramhound:正如 Yuck 所暗示的,“null”有时意味着“这个东西没有真值”。 “null”也可以表示“这个东西有一个真值,但我现在不知道它是什么,因为那个信息还没有输入到数据库中”。假设 missing 值是necessarily false,这是危险的。那个订单发货了吗? “我们不知道”的答案与“不”的答案不一样!如果是,那么一开始就不需要可空值。

标签: c# nullable boolean


【解决方案1】:

您也可以在具体情况下使用GetValueOrDefault

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

【讨论】:

  • 请注意,它在实体框架查询的上下文中不起作用。
【解决方案2】:

退一步思考问题。您想要一个小部件的集合,其中小部件被订购、小部件被运送或小部件被处理。

根据您对“有序”的了解,有四种可能的状态:

  • 此小部件已订购我知道(真的)
  • 此小部件未订购我知道(错误)
  • 此小部件已订购但我不知道(null)
  • 此小部件未订购但我不知道(null)

有四种状态,但只有三个值可能值。因此,如果“ordered”处于空状态你不知道它是否应该包含在查询结果中

编译器也不知道。

没有足够的信息可供编译器为您提供具有您想要的语义的查询。 编译器不会进行猜测并可能给您带来不好的结果;编译器会告诉你这里没有足够的信息,你需要做更多的工作来使查询明确。

你要做的就是说在你不知道答案的情况下该怎么做。查询“所有已订购、发货或处理的小部件”是不可能的,因为某些小部件我们不知道它们是否已订购、发货或处理,因此我们不知道是否包括他们与否。但是查询“我知道的所有小部件 已订购,或 我知道 已发货,或 我知道 已处理”是一个编译器可以理解的查询:

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

这意味着“如果我不知道它是否已发货,等等,假设它没有”。

您可能希望查询“所有确实已经或可能已经发货、订购或处理的小部件:

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

当没有足够的信息给出准确的结果时,编译器不会猜测你想在哪一边犯错;编译器可能猜错了,我们不代表您做出决定。你将不得不做出这个决定。

【讨论】:

  • +1 这个答案准确地解释了问题是什么以及如何解决它。它应该是公认的答案。
  • 亲爱的抄写员,请将此答案添加到经典中。
  • 如果您愿意,也可以使用where (tf.Shipped | tf.Ordered | tf.Processed) ?? falsewhere (tf.Shipped | tf.Ordered | tf.Processed) ?? true。 C# 专门为可为空的布尔操作数定义了运算符|,因此它不是简单的提升运算符。
【解决方案3】:
where ((tf.Shipped.HasValue && tf.Shipped.Value) 
   || (tf.Ordered.HasValue && tf.Ordered.Value) 
   || (tf.Processed.HasValue && tf.Processed.Value)) 

【讨论】:

  • @CodeInChaos 没错,但意思很明确。
【解决方案4】:
where ((tf.Shipped.HasValue && tf.Shipped.Value)
       || (tf.Ordered.HasValue && tf.Ordered.Value)
       || (tf.Processed.HasValue && tf.Processed.Value))

【讨论】:

  • 有趣的解决方案,运行时不会在 null .Value 上失败,因为如果 .HasValue(左侧)是 false,它不会检查 && 运算符语句的右侧。跨度>
  • 为了解释 TomislavMarkovski 的评论,我们必须认识到,如果所有的值都是空的,那么没有一个值是真的,因此 3 个 False 语句的 OR 是 False。同样,如果 HasValue 为 False,则 AND 语句始终为 False,运行时知道这一点,这就是您能够检查具有 Null 值的引用的值的原因。
【解决方案5】:

您需要确保表达式永远不会是null。您可以使用 null-coalesce 运算符??

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

【讨论】:

    【解决方案6】:

    试试

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

    【讨论】:

    • 强制结果为 bool(来自 bool?)。
    • 还有!!x,相当于x == true
    猜你喜欢
    • 2017-03-26
    • 2012-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-06
    • 1970-01-01
    • 2012-04-12
    • 2013-03-02
    相关资源
    最近更新 更多