Menu

C# if else 语句:else if 多分支、条件与常见错误

C# 中 if、else if 和 else 的工作方式:为什么条件必须是 bool,如何用 &&、|| 和 ! 组合判断,什么时候花括号很关键,用卫语句代替深层嵌套,以及 = 与 == 混用和多余分号导致的 bug。

本页包含可运行的编辑器。编辑、运行,立即查看输出。

if 语句只在条件为 true 时运行一段代码。else if 用来增加更多判断,else 则兜住所有判断都没匹配上的情况。

输出:

Order 120: shipping 0
Order 75.50: shipping 4.99
Order 20: shipping 9.99

条件从上到下依次检查,第一个为 true 的条件胜出。金额为 120 的订单匹配 >= 100,永远不会走到 >= 50 这个判断,所以最具体的条件要放在最前面。else if 并不是一个独立的关键字:它就是一个 else,而它的主体是另一个 if,所以 C# 中没有 elseif 或 elif。

条件必须是 bool

C# 从不把数字、字符串或对象当作 true 或 false。括号里的表达式必须是 bool 类型:

int count = 3;
if (count)          // error CS0029: Cannot implicitly convert type 'int' to 'bool'
if (count > 0)      // correct
if (name)           // error: a string is not a bool either
if (name != null)   // correct

这一规则消除了 C 和 JavaScript 中一整类 bug,在那些语言里 0、"" 和 null 会悄悄地被当作 false。代价是你每次都要把比较写出来,不过这也让下一位读代码的人能一眼看出你的意图。

用 &&、|| 和 ! 组合条件

&&(与)、||(或)和 !(非)用来组合布尔判断。&& 和 || 会短路:只有左边还不能决定结果时,右边才会执行。

输出:

maya: welcome
invalid or banned account
invalid or banned account
omar: age 9 rejected
invalid or banned account

传入 null 的那次调用之所以安全,是因为短路:一旦 username != null 为 false,username.Length 就不会被求值,也就不会抛出 NullReferenceException。如果把顺序换成 username.Length >= 3 && username != null,同样的调用就会崩溃。

&& 的优先级高于 ||,所以 a || b && c 的意思是 a || (b && c)。只要两者混用,就加上括号;编译器不需要,但读代码的人需要。单字符的 & 和 | 也能用于 bool,但它们总是对两边都求值。只有当右边带有必须发生的副作用时才使用它们。

花括号与“只管一条语句”规则

当分支只有一条语句时,花括号可以省略。省略后,不管缩进看起来如何,只有紧跟的下一条语句属于这个 if:

输出:

Reorder email sent
Stock: 12

库存明明充足,“Reorder email sent”还是打印了出来:尽管有缩进,第二个 WriteLine 其实在 if 之外。像 if (x == null) return; 这样的单行守卫不加花括号没问题;但凡以后可能再多一行的分支,都应该加上花括号。

另一个相关的 bug 是在条件后面紧跟一个分号。if (stock < 5); 用一条空语句结束了这个 if,后面的代码块会无条件执行。编译器会给出警告 CS0642,Possible mistaken empty statement,最好把它当作错误来对待。

条件中的 = 与 ==

= 是赋值,== 是比较。对大多数类型来说,误写成 = 是无法编译的,因为赋值表达式的结果就是被赋的值,而 int 不是 bool:

int score = 10;
if (score = 100) { }   // error CS0029: Cannot implicitly convert type 'int' to 'bool'

如果是 bool 变量,赋值表达式本身就是 bool,所以这个笔误能通过编译:

输出:

Access granted
isAdmin is now True

这个条件先覆盖了 isAdmin,然后判断的是新值。编译器会给出警告(CS0665,条件表达式中的赋值始终是常量),但构建仍然会成功。对于 bool,干脆不要写比较:if (isAdmin) 和 if (!isAdmin) 读起来更清楚,也不会出现这种笔误。

嵌套 if 与卫语句

每多一层嵌套,读代码的人就要在脑子里多记一个条件。当每个检查都是在拒绝无效输入时,应该提前返回,而不是把正常流程嵌套在所有检查里面:

输出:

ordered 2 x keyboard
error: no product
error: quantity must be positive
error: insufficient balance

同一个方法如果写成嵌套版本,会有三层 if,真正的工作放在最里层,底部还要用三个 else 分支逐层收尾。用了卫语句,每条规则都紧挨着它的错误信息,最后一行就是正常情况。同样的思路在循环中可以用 continue 实现。

在条件中声明变量

条件里可以声明一个变量,它在 if 内部可用。两种常见形式是 TryParse 方法的 out var 和 is 类型模式:

输出:

42: positive number 42
abc: not a number
-7: number -7, not positive
string of length 5

TryParse 遇到无效输入时返回 false 而不是抛出异常,所以天然适合放在 if 里。类型转换页面详细介绍了各种解析方法。

什么时候该用别的写法

  • 在两个值中选一个:条件运算符 condition ? a : b 比两个分支都在赋值的 if 更简洁。
  • 对同一个值有很多分支:switch 语句把一个值与多个常量 case 比较,比十行 else if 更容易浏览。
  • 把值映射成结果:当各分支只是数据不同时,用 Dictionary 查找可以取代一长串判断。

常见问题

C# 中 else if 怎么写?

把 else if 写成两个词:if (a) { ... } else if (b) { ... } else { ... }。条件从上到下依次判断,只有第一个为 true 的分支会执行,所以要把最具体的判断放在最前面。C# 没有 elif 或 elseif 关键字。

为什么 C# 里不能写 if (count)?

C# 的条件必须是 bool 类型。与 C 和 JavaScript 不同,int、字符串或对象永远不会被转换成 true 或 false,所以 if (count) 会报 CS0029 错误:Cannot implicitly convert type 'int' to 'bool'。把你想要的判断写出来:if (count > 0) 或 if (name != null)。

if 条件中的 && 和 & 有什么区别?

&& 会短路:如果左边为 false,右边根本不会被求值,正因如此 s != null && s.Length > 0 才是安全的。& 作用于两个 bool 时,每次都会对两边求值。|| 和 | 也是同样的道理。在条件中请使用 && 和 ||,除非你需要右边表达式的副作用。

C# 的 if 语句必须加花括号吗?

不是必须的。不加花括号时,if 只控制紧跟其后的一条语句。给第二行加上缩进并不会把它放进这个分支,这是一个经典的 bug 来源,所以大多数代码风格指南都建议每个分支都加上花括号。

C# 可以把 if else 写在一行吗?

如果是在两个值之间选择,用条件运算符:string label = score >= 50 ? "pass" : "fail";。如果是执行语句,if (x) DoA(); else DoB(); 写在一行也是合法的,但比起带花括号的代码块,它更难阅读,也更难扩展。

Coddy 编程语言插图

和 Coddy 一起学编程

开始