C# 8.0本质论
上QQ阅读APP看书,第一时间看更新

4.5 布尔表达式

if语句中包含在圆括号内的部分是布尔表达式,称为条件。代码清单4.28突出显示了条件。

代码清单4.28 布尔表达式

许多控制流程语句都要使用布尔表达式,其关键特征在于总是求值为true或false。input<9要成为布尔表达式就必须返回bool值。例如,编译器不允许将布尔表达式写成x=42,因为它的作用是对x进行赋值,并返回新值,而不是检查x的值是否等于42。

语言对比:C++——错误地使用=来代替==

C#消除了C/C++的一个常见的编码错误。代码清单4.29在C++中不会出错。

代码清单4.29 C++允许将赋值作为条件

虽然上述代码表面上是检查input是否等于9,但正如第1章讲过的那样,=代表的是赋值操作符,而不是检查相等性的操作符。从赋值操作符返回的是赋给变量的值,本例中就是9。然而,作为int的9无法被判定为布尔表达式,所以是C#编译器不允许的。C和C++将非零整数视为true,将零视为false。相反,C#要求条件必须是布尔类型,不允许整数。

4.5.1 关系操作符和相等操作符

关系和相等操作符判断一个值是否大于、小于或等于另一个值。表4.2总结了所有关系和相等操作符。它们都是二元操作符。

表4.2 关系和相等操作符

和其他许多编程语言一样,C#使用相等操作符==来测试相等性。例如,判断input是否等于9要使用input==9。相等操作符使用两个等号,赋值操作符则使用一个。C#的惊叹号代表NOT,所以用于测试不等性的操作符是!=。

关系和相等操作符总是生成bool值,如代码清单4.30所示。

代码清单4.30 将关系操作符的结果赋给bool变量

井字棋程序的完整代码清单使用相等操作符判断玩家是否退出游戏。代码清单4.31的布尔表达式包含一个OR(||)逻辑操作符,下一节将详细讨论它。

代码清单4.31 在布尔表达式中使用相等操作符

4.5.2 逻辑操作符

逻辑操作符获取布尔操作数并生成布尔结果。可用逻辑操作符合并多个布尔表达式来构成更复杂的布尔表达式。逻辑操作符包括|、||、&、&&和^,对应OR、AND和XOR(异或)。OR和AND的|和&版本很少用,原因稍后讨论。

OR操作符

在代码清单4.31中,如果玩家输入quit,或直接按回车键而不输入任何值,就认为想退出程序。为了允许玩家以两种方式退出,程序使用了逻辑OR操作符||。||操作符对两个布尔表达式进行求值,任何一个为true就返回true,如代码清单4.32所示。

代码清单4.32 使用OR操作符

注意使用布尔OR操作符时,不一定每次都要对操作符两边的表达式进行求值。和C#的所有操作符一样,OR操作符从左向右求值,所以假如左边求值为true,那么右边可以忽略。换言之,如hourOfTheDay的值为33,那么(hourOfTheDay > 23)会返回true,所以OR操作符会忽略右侧表达式。这种短路求值方式同样适合布尔AND操作符。注意,此处不需要括号,逻辑操作符的优先级低于关系操作符。然而,对于新手读者来说,在子表达式中加括号更为清晰。

AND操作符

布尔AND操作符&&在两个操作数求值都为true的前提下才返回true。任何操作数为false都会返回false。

代码清单4.33判断当前小时数是否大于10且小于24[1]。如同时满足这两个条件,就输出一条消息表明当前是工作时间。和OR操作符一样,AND操作符也并非每次都要对右边的表达式进行求值。如左边的操作数返回false,则不管右边的操作数是什么,最终结果肯定为false,所以“运行时”会忽略右边的操作数。

代码清单4.33 使用AND操作符

XOR操作符

^符号是异或(Exclusive OR,XOR)操作符。若应用于两个布尔操作数,那么只有在两个操作数中仅有一个为true的前提下,XOR操作符才会返回true,如表4.3所示。

与布尔AND和OR操作符不同,布尔XOR操作符不支持短路运算。它始终都要检查两个操作数,因为除非确切知道两个操作数的值,否则不能判定最终结果。注意将表4.3的XOR操作符换成!=操作符,结果完全一样。

表4.3 XOR运算表

4.5.3 逻辑求反操作符

逻辑求反操作符(!)有时也称为NOT操作符,作用是反转一个bool数据类型的值。它是一元操作符,只需一个操作数。代码清单4.34演示了它如何工作,输出4.16展示了结果。

代码清单4.34 使用逻辑求反操作符

输出4.16

valid最开始的值为false。求反操作符对valid的值取反,将新值赋给result。

4.5.4 条件操作符

可用条件操作符取代if-else语句来选择两个值中的一个。条件操作符同时使用一个问号和一个冒号,常规格式如下:

条件操作符是三元操作符,需要三个操作数:condition、consequence和alternative。(由于它是C#中唯一的三元操作符,因此通常称为三元操作符,但用它的名称来称呼它比用操作数数量更清楚。)类似于逻辑操作符,条件操作符也采用了某种形式的短路求值。如condition求值为true,则条件操作符只求值consequence;否则只求值alternative。操作符的结果是被求值的表达式。

代码清单4.35展示了如何使用条件操作符。该程序的完整清单是Chapter03\TicTacToe.cs。

代码清单4.35 条件操作符

程序作用是交换当前玩家。它检查当前值是否为2。这是条件语句的condition部分。如结果为true,条件操作符返回consequence值1;否则返回alternative值2。和if语句不同,条件操作符的结果必须赋给某个变量(或作为参数传递),不能自成语句。

设计规范

·考虑使用if/else语句而不是过于复杂的条件表达式。

C#语言要求条件操作符的consequence和alternative表达式类型一致,而且在判定类型时不会检查表达式的上下文。例如,f ? "abc" : 123不是合法的条件表达式,因为consequence和alternative分别是字符串和数字,相互不能转换。即使object result=f ? "abc" : 123;这样的语句,C#编译器也会认为非法,因为兼容两个表达式的类型(这里是object)在条件表达式的外部。

[1] 程序员典型的工作时间。