bool 变量可以包含true或false,而 bool?也可以为null。
为什么我们需要bool的第三个值? 如果它不是 true ,那么它是什么,它是== false
你能否建议我喜欢 bool?。
由于
答案 0 :(得分:32)
出于多种原因,某些事情可能是真的,错误的或未定义的。如何回答“你的第三个孩子是女孩吗?”如果一个人只有两个孩子?真假都是不正确的。 Null适合说比较不适用。
答案 1 :(得分:13)
各种答案一般都讨论了可空类型的重要性。可以为null的布尔值提供额外的答案。在C#中很难理解,但如果你在任何数据库中查看空值逻辑,这很容易理解。
假设您正在跟踪Shipments
的列表或表格。 Shipment
有一个DeliveryDate
,当然,在货物发货很久之后,您可能不知道这些信息,并且可能至少在货物实际发货后几天,当UPS最终绕过来通知你。当然,DeliveryDate
是Nullable<DateTime>
(或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
总是true
,对吗?不是在你处理空值时。
即便是这个也无法得到所有结果:
var deliveredAnytime = shipments.Where(s =>
(s.DeliveryDate >= DateTime.Today.AddDays(-7)) ||
(s.DeliveryDate < DateTime.Today.AddDays(-7)));
那怎么可能呢?
为了准确地表示此逻辑,您需要一个不正确或 false的条件。而且,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<bool>
吗?因此,您可以避免在自己的代码中陷入此陷阱:
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<bool>
)作为结果。
这样,调用者可以决定如何处理“我不知道”的响应,而不是简单地选择默认值。其他任何意味着你的班级撒谎。
答案 2 :(得分:10)
null
值表示“无值”或“未知值”。在这种情况下,它不是真的也不是假的,而是 undefined 。
答案 3 :(得分:5)
当某些事情尚未得到回答时,这是好事 - 想一想调查问卷。你有一个y / n问题列表,只有一些已被回答。您不希望将true或false发布到数据库表,因为用户尚未回答该问题。
答案 4 :(得分:3)
除了true或false之外,它可能是未知的..在数据库中,NULL通常表示未知或没有值
答案 5 :(得分:3)
懒惰编程!
public bool MyProp
{
get { return (myProp = myProp ?? GetPropValue()).Value; }
}
private bool? myProp;
答案 6 :(得分:2)
答案 7 :(得分:2)
我在过滤值中使用它。基本上我在数据库中有一个bool字段,但我想要三种状态:只返回值为true的行,只返回值为false的行,不过滤并返回所有行。
如果没有可空的bool,我将不得不使用枚举或第二个bool来确定“按此字段过滤是/否”这会增加膨胀。
答案 8 :(得分:1)
可以为空可能表示如果你的程序可能需要知道那个bool没有被设置或初始化
答案 9 :(得分:1)
好吧,我可以看到它被用作“尚未确定”的东西,我一直使用bool,有时只有两个值不够!!例如:
bool? bl;
bl = true; //Yes
bl = false; //No
bl = null; // Not determined, so do nothing
在我看来,它只是布尔的第三个价值。
答案 10 :(得分:1)
如果您要使用Nullable bool,我会考虑使用Enum或其他数据结构。当NULL的含义未知时,它可以帮助您避免错误。
最近,我错误地处理了Nullable bool。我不会详细介绍这个错误,但我只想说它要求完全回滚已经够糟糕了。我开始想知道在大多数应用程序中使用它是多么实用。 (在某种程度上,由于这个愚蠢的错误,我试图坚持自己的骄傲)
然后,我发现了这篇文章和李的接受答案。
这似乎有道理,但是我用它花费的时间越多,答案在实践中变为FALSE而不是NULL。 NULL太模糊了。
在回答这个问题之前,必须为NULL分配一个非常具体的含义。 NULL是否表示计算中存在错误?如果在确定只有两个孩子之前计算中有错误怎么办? (我还会争辩说,如果确实只有两个孩子,可以在问题提交给该计划之前处理。)
因为我们不知道NULL意味着什么,因为它绝对不是真的(因为,它怎么可能?),最好的答案是假的。
此外,如果此问题确实返回NULL,我们已经为域引入了新定义。这个定义的范围是什么?
因此看起来TRUE或FALSE状态代表结果的确定性。可以在至少三种不同状态中设想NULL。例如,“托马斯昨晚去了酒吧。”
是的 - 是的,托马斯去了酒吧。 (如果你认识托马斯,最有可能的回答) 是的 - 不,托马斯没有去酒吧。 空 - 嗯? 可知 - 第一次计算出错了。例如。你问托马斯这个问题,但他回答时打了个喷嚏,让你暂时失聪。再问他一次就能得到答案。
不可知 - 酒吧被烧毁,托马斯跳过城镇。没有现实的方法来得到答案。 (请不要在这里戳洞,但我知道你会这样做)
不适用 - 请参阅上面关于三个孩子的例子,但是,请选择酒吧和托马斯。
NULL在这里意味着什么?必须根据具体情况确定NULL的含义。这就是为什么我认为使用Enum或其他结构通常更好,因为它更优雅地暴露了非二进制返回值背后的意图。
答案 11 :(得分:0)
您希望使用它来涵盖“如果用户既没有指定既不是真也不指定该怎么办?”的情况。
这只是一种涵盖所有可能结果的方法。
答案 12 :(得分:0)
假设已下订单但尚未发货。 Order.ShippedDate
的价值是什么?
处理这种问题的老式方法是使用像DateTime.MinValue
这样的神奇值。还有其他方法可以解决此问题(例如,包装类型或额外的bool
标志,表明订单尚未发货)。这些都不是很令人满意。我们需要的是一种统一的方法来处理遗漏或未知值的问题。
因此,现代方法是允许Order.ShippedDate
采用语义捕获订单尚未发货的值。这是可空类型扮演的角色。从语义上讲,您应该将Nullable<T>
的{{1}}实例视为HasValue
,表示“缺失”或“未知”。
此外,数据库长期允许列允许false
。例如,您可以使用允许null的整数值列。如果不允许可空null
s,如何从代码中与这样的列进行交互?同样,您可以使用上面提到的方法,但是当语言具有用于语义捕获我们正在尝试建模的情况的内置工具时,它会更好。
答案 13 :(得分:0)
这是另一个用例。考虑具有布尔属性的分层数据结构。在父项上设置此类属性将应用于其所有子项,除非明确设置它们。考虑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)
答案 14 :(得分:0)
我认为在C#2中添加可空类型的主要动机(至少它是这样的:-))是数据库。在数据库中,任何数据类型都可以具有NULL
值,并且在将这些数据映射到C#时,这是一个问题。 Nullable类型允许您非常优雅地处理此问题 - 您可以使用int?
,bool?
和其他人。例如,它们用于LINQ to SQL。
第三个值对布尔值意味着什么,当然这取决于应用程序。我想通常,这意味着值/字段不可用。