Nullable 类型有什么用?

布尔变量可以保持真或假,而布尔? 也可以为空。

为什么我们需要bool的第三个值? 如果它不是真的 ,它是什么,它是== false

你能提出一个我喜欢布尔的场景吗? 代替。

谢谢

出于多种原因,某些事情可能是真实的,错误的或未定义的。 如何回答“你的第三个孩子是女孩吗?” 如果一个人只有两个孩子? 真假都是不正确的。 Null适合说比较不适用。

各种答案一般都讨论了可空类型的重要性。 可以为null的布尔值提供额外的答案。 在C#中很难理解,但如果你在任何数据库中查看空值逻辑,这很容易理解。

假设您正在跟踪Shipments清单或表格。 Shipment有一个DeliveryDate ,但当然,您不知道这些信息,直到发货很久,并且可能至少在货物实际交付后几天,当UPS最终通知您时。 当然, DeliveryDateNullable (或DateTime? )。

您想要检索上周交付的所有货件的清单。 所以你写这个:

 var deliveredThisWeek = shipments.Where(s => s.DeliveryDate >= DateTime.Today.AddDays(-7)); 

是否应包含交货日期为null货件? (当然,答案是否定的 。)

好的,那么这个怎么样:

 var deliveredBeforeThisWeek = shipments.Where(s => s.DeliveryDate < DateTime.Today.AddDays(-7)); 

这些结果中是否应包含交货日期为null货件? 答案仍然否定的

所以现在你有一个好奇的情况。 您可能会认为在这两个查询之间,您将收到系统中的所有货件。 A | !A A | !A总是true ,对吧? 不是在你处理空值时。

即便是这个也无法得到你所有的结果:

 var deliveredAnytime = shipments.Where(s => (s.DeliveryDate >= DateTime.Today.AddDays(-7)) || (s.DeliveryDate < DateTime.Today.AddDays(-7))); 

那怎么可能呢?

为了准确地表示此逻辑,您需要一个不是真假的条件。 而且,C#在这里是一个不好的例子,因为它没有像你真正期望的那样实现逻辑。 但在SQLese中,它是有道理的,因为:

 [DeliveryDate >= BeginningOfWeek] = NULL [DeliveryDate < BeginningOfWeek] = NULL 

显然, NULL OR NULL仍为NULL ,而不是TRUE 。 这就是为什么你可以正确地说货物在本周开始之前没有交付, 并且之后没有交付。 或者,更准确地说,我们不知道它何时交付,因此我们无法安全地说它确实符合这些条件。

但C#并不是那么一致。 在C#中,如果DeliveryDate为null,则:

 (s.DeliveryDate >= beginningOfWeek) == false (s.DeliveryDate < endOfWeek) == false 

这为我们上面的查询提供了正确的答案,所以你可能会想要说常规布尔逻辑足够好,除了这一个搞砸了:

 var deliveredThisWeek = shipments.Where(s => !(s.DeliveryDate < DateTime.Today.AddDays(-7)); 

啊哈...现在它给我们回送null交货日期! 这不对! 在有人说“@Aaronaught,你在谈论什么,当然是对的!这些货物在上周之前没有交付,所以条件应该覆盖他们!” ,停下来思考一下。

NULL实际上并不意味着它们没有被传递。 NULL表示我们不知道它们何时被传递。 职员可能会在明天拿到确认函,并在两周前填写DeliveryDate ,使我们刚收到的数据无效。 应该有来自该查询的空实例,但是有。 如果在SQL中编写相同的查询,则会排除这些结果。

所以,当C#显然没有时,你为什么要关心Nullable ? 因此,您可以避免在自己的代码中陷入此陷阱:

 public static bool? IsThisWeek(DateTime? dt) { return (dt != null) ? (bool?)(dt.Value > DateTime.Today.AddDays(-7)) : null; } var deliveredBeforeThisWeek = shipments.Where(s => (!IsThisWeek(s.DeliveryDate) == true)); // Or, the equivalent: var alsoDeliveredBeforeThisWeek = shipments.Where(s => (IsThisWeek(s.DeliveryDate) == false)); 

这有点尴尬,但是正确的。 我们编写了一个或多或少正确地传达其意图的查询,并且(bool?)null不等于true false ,因此我们在两种情况下都得到了正确的结果。

如果您需要评估答案可能是“我不知道”的情况 - 请使用bool? (AKA Nullable作为结果

这样,调用者可以决定如何处理“我不知道”的响应,而不是简单地选择默认值。 别的什么意味着你的class级撒谎

null值表示“无值”或“未知值”。 在这种情况下,它不是真的,也不是假的,而是未定义的

请参阅: http : //en.wikipedia.org/wiki/Many-valued_logic

当一些事情还没有得到回答时,这是好事 – 想想调查问卷。 你有一个y / n问题列表,只有一些已被回答。 您不希望将true或false发布到数据库表,因为用户尚未回答该问题。

除了true或false之外,它可能是未知的。在数据库中,NULL通常表示未知或没有值

懒惰的编程!

 public bool MyProp { get { return (myProp = myProp ?? GetPropValue()).Value; } } private bool? myProp; 

空值表示

  • 我不知道。
  • 目前数据不足
  • 盒子打开前猫的状态
  • 我还没有下定决心
  • 利润

空值表示Mu

我在过滤值中使用它。 基本上我在数据库中有一个bool字段,但我想要三种状态:只返回值为true的行,只返回值为false的行,不过滤并返回所有行。

如果没有可空的bool,我将不得不使用枚举或第二个bool来确定“按此字段筛选是/否”这将增加膨胀。

可以为空可以表示如果你的程序可能需要知道的话,bool没有被设置或初始化

好吧,我可以看到它被用作“尚未确定”的东西,我一直使用bool,有时只有两个值不够!! 例如:

 bool? bl; bl = true; //Yes bl = false; //No bl = null; // Not determined, so do nothing 

在我看来,它只是bool的第三个价值。

如果您即将使用Nullable bool,我会考虑使用Enum或其他数据结构。 当NULL的含义未知时,它可以帮助您避免错误。

最近,我错误地处理了Nullable bool。 我不会详细介绍这个错误,但我们只是说它要求完全回滚已经够糟糕了。 我开始想知道在大多数应用程序中使用它是多么实用。 (在某种程度上,由于这个愚蠢的错误,我试图坚持自己的骄傲🙂)

然后,我遇到了这个post和李的接受答案。

这似乎是有道理的,但是我用它花费的时间越多,答案在实践中变为FALSE而不是NULL。 NULL太模糊了。

在回答这个问题之前,必须为NULL分配一个非常具体的含义。 NULL是否表示计算中存在错误? 如果在确定只有两个孩子之前计算中有错误怎么办? (我还会争辩说,如果确实只有两个孩子,可以在问题提交给该计划之前处理。)

因为我们不知道NULL意味着什么,因为它绝对不是真的(因为,它怎么可能?)最好的答案是假的。

此外,如果此问题确实返回NULL,我们已经向域引入了新定义。 这个定义的范围是什么?

因此,看起来TRUE或FALSE状态表示结果的确定性。 可以在至少三种不同状态中设想NULL。 例如,“托马斯昨晚去了酒吧”这句话。

是的 – 是的,托马斯去了酒吧。 (如果你认识托马斯,最有可能的回答)假 – 不,托马斯没有去酒吧。 NULL – 嗯? 可知 – 第一次计算出错了。 例如,你问托马斯这个问题,但他回答时打了个喷嚏,让你暂时失聪。 再问他一次就能得到答案。

不可知 – 酒吧被烧毁,托马斯跳过城镇。 没有现实的方法来得到答案。 (请不要戳这个洞,但我知道你会)

不适用 – 请参阅上面关于三个孩子的例子,而不是栏和托马斯。

NULL在这里意味着什么? 确定必须根据具体情况执行NULL意味着什么。 这就是为什么我认为使用Enum或其他结构通常更好,因为它更优雅地暴露了非二进制返回值背后的意图。

您希望使用它来涵盖“如果用户既没有指定既不指定也不指定错误怎么办?”的情况。

这只是一种涵盖所有可能结果的方法。

假设已下订单但尚未发货。 Order.ShippedDate的价值是Order.ShippedDate

处理这个问题的老式方法是使用像DateTime.MinValue这样的神奇值。 还有其他方法可以解决此问题(例如,包装类型或附加的bool标志,表明订单尚未发货)。 这些都不是很令人满意。 所需要的是一种统一的方法来处理丢失或未知值的问题。

因此,现代方法是允许Order.ShippedDate采用语义捕获订单尚未发货的值。 这是可空类型扮演的角色。 从语义上讲,你应该想到一个Nullable的实例,其中HasValuefalse ,表示“缺失”或“未知”。

此外,数据库长期允许列允许null 。 例如,您可以使用允许null的整数值列。 如果你不允许可以为空的int你如何从代码中与这样的列交互? 同样,您可以使用上面提到的方法,但是当语言具有用于语义捕获我们正在尝试建模的情况的内置工具时,它会更好。

这是另一个用例。 考虑具有布尔属性的分层数据结构。 在父项上设置此类属性将应用于其所有子项,除非明确设置它们。 考虑Windows中的文件和文件夹的只读权限(具有三态复选框)。

 Parent1(readonly: true, evaluates true) |-Parent2(readonly: null, evaluates true) |-Child1(readonly: false, evaluates false) |-Child2(readonly: null, evaluates true) |-Parent3(readonly: false, evaluates false) |-Child1(readonly: false, evaluates false) |-Child2(readonly: null, evaluates false) 

我认为在C#2中添加可空类型的主要动机(至少它是这样的:-))是数据库。 在数据库中,任何数据类型都可以具有NULL值,并且在将这些数据映射到C#时,这是一个问题。 可空类型允许您非常优雅地处理这个问题 – 您可以使用int?bool? 和别的。 它们用于LINQ to SQL中。

第三个值对布尔值意味着什么,当然这取决于应用程序。 我想通常,这意味着值/字段不可用。