为什么不将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的并不合理。 在某些情况下这是有道理的,但在其他情况下却没有。 例如,假设您有一个可以有三个值的标志: setunsetun-initialized 。 在这种情况下, settrueunsetfalseun-initializednull 。 如您所见,在这种情况下, 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位。

也就是说,机器代码中的某些东西要么“相等”,“零”,“大”,“小”,“大于或等于”,要么“小于或等于”。 没有nullfalsetrue这样的东西。

按照惯例, true1false0null指针为0x00000x0000000000000000 ,具体取决于地址总线宽度。

C#是例外之一,因为它是间接类型,其中两个可能的值01不是立即值,而是结构的索引 (在C中认为enum ,或在x86程序集中为PTR )。

这是设计的。

然而,重要的是要注意,这样的设计决策是精心制作的决策,而传统的,直截了当的方式是假设0nullfalse是相等的。

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)是好的,因为它还增加了代码的清晰度,更容易理解你真正检查的内容。