为什么不将null评估为false?

时间:2010-07-07 17:06:59

标签: c# null type-conversion conditional

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...
}

11 个答案:

答案 0 :(得分:23)

这是C#语言中的特定设计功能:if statements accept only a bool

IIRC这是为了安全:具体来说,你的第一个if (someClass = someValue)无法编译。

编辑:一个好处是它使if (42 == i)约定(“yoda比较”)变得不必要。

答案 1 :(得分:22)

“我认为假设null意味着错误”

是合理的

不在C#中。 false是一个布尔结构,一个值类型。值类型不能具有空值。如果你想做你所做的事情,你必须创建特定类型的自定义转换器为布尔值:

public class MyClass
{
    public static implicit operator bool(MyClass instance)
    {
        return instance != null;
    }
}

通过上述内容,我可以做到:

if (instance) {

}

答案 2 :(得分:13)

“我认为假设null意味着错误”

是合理的

我不同意。恕我直言,错误意味着“不”。 Null意为“我不知道”;即完全不确定。

答案 3 :(得分:5)

在数据类型的实例中会想到一件事,比如int? Int不能为空,所以它们总是评估为真吗?你可以假设int = 0是假的,但是开始变得非常复杂,因为0是一个有效值(其中0可以评估为true,因为编程器设置它)而不仅仅是默认值。
有很多边缘情况,其中null不是一个选项,或者有时它是一个选项,有时则不是。

他们提出这样的事情来保护程序员不犯错误。它与你在案例陈述中无法做到的原因相同。

答案 4 :(得分:5)

只需使用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

答案 5 :(得分:4)

据我所知,这是一个你在动态语言中看到的功能,C#不是这种功能(根据语言规范if只接受bool或表达式计算为{{1 }})。

我认为在每个案例中boolnull是不合理的。在某些情况下这是有道理的,但在其他情况下却没有。例如,假设您有一个可以有三个值的标志: set unset un-initialized 。在这种情况下, set 将为false未设置将为true,而未初始化将为{{ 1}}。如您所见,在这种情况下,false的含义不是null

答案 6 :(得分:3)

因为null和false是不同的东西。

一个完美的例子是布尔? FOO

如果foo的值为true,则其值为true 如果foo的值为false,则其值为false 如果foo没有赋值,则其值为null。

这是三个逻辑上独立的条件。

另一种想法 “我欠你多少钱?
Nothing ”和“我没有那些信息”是两个截然不同的答案。

答案 7 :(得分:3)

  

null没有的原因是什么   在条件中评估为假?

     

我首先想到的是作业   避免使用=代替的错误   ==

这不是原因。我们知道这一点,因为如果要比较的两个变量恰好是bool类型,那么代码将编译得非常愉快:

bool a = ...
bool b = ...

if (a = b)
    Console.WriteLine("Weird, I expected them to be different");

如果b为真,则打印消息(a现在为真,使后续调试体验与消息一致,从而使您更加困惑......)

null无法转换为bool的原因只是C#避免了隐式转换,除非设计者要求用户定义类型。 C ++历史书充满了由隐式转换引起的痛苦故事。

答案 8 :(得分:3)

在结构上,大多数无法想到任何技术理由的人应该等于虚假"弄错了。

代码由CPU运行。 大多数(如果不是全部)CPU具有位组位组的解释。也就是说,可以是Preferences > Java>Build Path > Classpath Variables.01byteworddword等等。< / p>

请注意,在x86平台上,字节是八位字节(8位),字通常是16位,但这不是必需的。较旧的CPU有4位字,甚至今天也是如此。低端嵌入式控制器通常使用每个字7或12位。

那就是说,有些事情是&#34;等于&#34;,&#34;零&#34;,&#34;更大&#34;,&#34;更少&#34;,&#34;更大或等于&#34;,或&#34;少于或等于&#34;在机器代码中。没有qwordnullfalse

作为惯例,truetrue1false0指针为null,{{1 },0x000x0000,具体取决于地址总线宽度。

C#是例外之一,因为它是间接类型,其中两个可能的值0x000000000x0000000000000000不是立即值,而是索引一个结构(在C中考虑0,或在x86汇编中考虑1

这是设计的。

重要的是要注意,此类设计决策是精心制作决策,而传统,直接方式是假设enum,{ {1}}和PTR相等。

答案 9 :(得分:2)

C#没有像C ++那样转换参数。如果希望if语句接受该值,则需要在布尔值中显式转换该值。

答案 10 :(得分:1)

与PHP,Perl等语言相比,它只是c#的类型系统。

条件只接受Boolean个值,null不具有Boolean类型,因此它在那里不起作用。

至于你在另一个评论中提到的C / C ++中的NULL例子,必须要说C和C ++都没有布尔类型(事后C ++通常有一个针对bool的类型转换,解析为int,但这是另一回事并且它们也没有空引用,只有NULL(=&gt; 0) - 指针。

当然,编译器设计人员可以将任何可空类型的自动转换实现为布尔值,但这会导致其他问题,即:

假设foo null

if (foo)
{
  // do stuff
}

哪种状态是真的?
总是如果它不是空的?
但是,如果您希望您的类型可以转换为布尔值(即来自您的三态或量子逻辑类),该怎么办?

这意味着你会有两种不同的转换,包括隐式转换和显式转换,这两种转换都会有不同的行为。

我甚至不敢想象如果你做的话会发生什么

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