为什么不将null评估为false?
在条件句中null
为什么不评估为false
的原因是什么?
我首先想到的是分配以避免使用=
而不是==
的错误,但编译器很容易不允许这样做。
if (someClass = someValue) // cannot convert someClass to bool. Ok, nice if (someClass) // Cannot convert someClass to bool. Why? if (someClass != null) // More readable?
我认为假设null
意味着false
是相当合理的。 还有其他语言也使用它,因为它没有我的错误。
编辑:我当然是指参考类型。
Daniel Earwicker关于赋值错误的一个很好的评论…这个编译没有警告,因为它评估为bool
:
bool bool1 = false, bool2 = true; if (bool1 = bool2) { // oops... false == true, and bool1 became true... }
它是C#语言中的特定设计function: if
语句只接受bool
。
IIRC这是为了安全:具体来说,你的第一个if (someClass = someValue)
无法编译。
编辑:一个好处是它使if (42 == i)
约定(“yoda比较”)不必要。
“我认为假设null意味着错误是相当合理的”
不在C#中。 false是一个布尔结构,一个值类型。 值类型不能具有空值。 如果你想做你所做的,你必须创建你的特定类型的自定义转换器布尔值:
public class MyClass { public static implicit operator bool(MyClass instance) { return instance != null; } }
有了上述,我可以这样做:
if (instance) { }
等等
“我认为假设null意味着错误是相当合理的”
我不同意。 恕我直言,错误意味着“不”。 Null的意思是“我不知道”; 即完全不确定。
在数据类型的实例中会想到一件事,比如int? Int不能为null,所以它们总是评估为true吗? 你可以假设int = 0是假的,但是开始变得非常复杂,因为0是一个有效值(其中0可能评估为true,因为编程器设置它)而不仅仅是默认值。
有很多边缘情况,其中null不是一个选项,或者有时它是一个选项,有时则不是。
他们提出这样的事情来保护程序员不犯错误。 它与你在案例陈述中无法做到的原因相同。
只需使用if(Convert.ToBoolean(someClass))
http://msdn.microsoft.com/en-us/library/wh2c31dd.aspx
参数
value类型:System.Object实现IConvertible接口的对象,或null。 回报价值
类型:System.Boolean true或false,它反映了通过为基础类型的值调用IConvertible.ToBoolean方法返回的值。 如果value为null,则该方法返回false
据我所知,这是一个你在动态语言中看到的function,C#不是(根据语言规范, if
只接受bool
或评估为bool
的表达式)。
我认为在每种情况下假设null
都是false
的并不合理。 在某些情况下这是有道理的,但在其他情况下却没有。 例如,假设您有一个可以有三个值的标志: set , unset和un-initialized 。 在这种情况下, set为true
, unset为false
, un-initialized为null
。 如您所见,在这种情况下, null
的含义不是false
。
因为null和false是不同的东西。
一个完美的例子是布尔? FOO
如果foo的值为true,则其值为true。
如果foo的值为false,则其值为false
如果foo没有赋值,则其值为null。
这些是三个逻辑上独立的条件。
想想另一种方式
“ 我欠你多少钱? ”
“ 没什么 ”和“ 我没有那些信息 ”是两个截然不同的答案。
在条件句中null为什么不评估为false的原因是什么?
我首先考虑分配以避免使用
=
而不是==
的错误
这不是原因。 我们知道这一点,因为如果被比较的两个变量恰好是bool
类型,那么代码将非常愉快地编译:
bool a = ... bool b = ... if (a = b) Console.WriteLine("Weird, I expected them to be different");
如果b
为真,则打印消息(现在是a
,使后续调试体验与消息一致,从而使您更加困惑……)
null
无法转换为bool
的原因只是C#避免了隐式转换,除非用户定义类型的设计者请求。 C ++历史书充满了由隐式转换引起的痛苦故事。
在结构上,大多数“无法想到任何技术理由无效应该等于假”的人都会弄错。
代码由CPU运行。 大多数(如果不是全部)CPU具有位 , 位 组和位组的 解释 。 也就是说,有些东西可以是0
,一个byte
,一个word
,一个dword
,一个qword
等等。
请注意,在x86平台上,字节是八位字节(8位),字通常是16位,但这不是必需的。 较旧的CPU具有4位字,即使是今天的低端嵌入式控制器也经常使用每字7或12位。
也就是说,机器代码中的某些东西要么“相等”,“零”,“大”,“小”,“大于或等于”,要么“小于或等于”。 没有null
, false
或true
这样的东西。
按照惯例, true
为1
, false
为0
, null
指针为0x0000
或0x0000000000000000
,具体取决于地址总线宽度。
C#是例外之一,因为它是间接类型,其中两个可能的值0
和1
不是立即值,而是结构的索引 (在C中认为enum
,或在x86程序集中为PTR
)。
这是设计的。
然而,重要的是要注意,这样的设计决策是精心制作的决策,而传统的,直截了当的方式是假设0
, null
和false
是相等的。
C#没有像C ++那样转换参数。 如果希望if
语句接受该值,则需要在布尔值中显式转换该值。
它只是c#的类型系统,与PHP,Perl等语言相比。
条件只接受Boolean
值,null不具有Boolean
值类型,因此它不能在那里工作。
至于你在另一个评论中提到的C / C ++中的NULL例子,必须要说C和C ++都没有布尔类型(因为C ++通常有一个针对bool的类型转换,解析为int,但这是另一个问题)和它们也没有空引用,只有NULL(=> 0) – 指针。
当然,编译器设计人员可以将任何可空类型的自动转换实现为布尔值,但这会导致其他问题,即:
假设foo
不为 null
:
if (foo) { // do stuff }
哪种状态是真的?
总是如果它不是空的?
但是,如果您希望您的类型可以转换为布尔值(即来自您的三态或量子逻辑类),该怎么办?
这意味着你将有两个不同的转换为bool,隐式和显式,这两种行为都会有不同的表现。
我甚至不敢想象如果你这样做会发生什么
if (!!foo) // common pattern in C to normalize a value used as boolean, // in this case might be abused to create a boolean from an object { }
我认为强制(foo == null)
是好的,因为它还增加了代码的清晰度,更容易理解你真正检查的内容。