C# 条件与循环
程序的"灵魂"是做判断 + 重复干活——这正是控制流做的事。这一篇我们把 C# 的条件(if、switch)和循环(for、foreach、while)全部过完,顺便认识一下现代 C# 的switch 表达式,它是写干净代码的关键工具。
一、if-else 条件
最基础的条件判断。语法和 C/Java 一样:
int score = 78;
if (score >= 90)
{
Console.WriteLine("优秀");
}
else if (score >= 60)
{
Console.WriteLine("及格");
}
else
{
Console.WriteLine("不及格");
}
// 单行可省略花括号(不推荐,易出错)
if (score > 100)
Console.WriteLine("无效分数");
// 条件表达式可以是复杂逻辑
bool hasHomework = true;
bool finished = false;
if (!finished && hasHomework && score > 60)
{
Console.WriteLine("继续做作业");
}几个建议:
- 始终用花括号,即使单行——避免后续维护加代码出 bug。
- 判断不要写
== true:用if (ok)而不是if (ok == true)。 - 判断 null 用
is null或is not null,比== null更安全(避开运算符重载)。
二、switch 语句
多分支判断,比一长串 if-else 清晰:
// 传统 switch 语句
int day = 3;
switch (day)
{
case 1:
Console.WriteLine("周一");
break; // 必须有 break,不像 C/C++ 可隐式贯穿
case 2:
Console.WriteLine("周二");
break;
case 6:
case 7:
Console.WriteLine("周末");
break;
default:
Console.WriteLine("工作日");
break;
}
// switch 必须有 break/return/goto,不能贯穿(除非 case 之间无语句)
// 这避免了 C/C++ 忘写 break 的经典 bugC# 的 switch 强制每个 case 用 break/return(不能贯穿),避免了 C/C++ 忘写 break 的经典 bug。空 case 可以连写(case 6: case 7: 表示共享代码)。
三、switch 表达式(C# 8+,强推!)
这是现代 C# 的大杀器——把 switch 变成"返回值的表达式",配合模式匹配极其优雅:
// C# 8+ switch 表达式(强推!)
int score = 78;
string grade = score switch
{
>= 90 => "A",
>= 80 => "B",
>= 60 => "C",
_ => "D" // _ 是弃元,匹配其他所有情况
};
// "C"
// 枚举 switch
enum TrafficLight { Red, Yellow, Green }
TrafficLight light = TrafficLight.Yellow;
string action = light switch
{
TrafficLight.Red => "停",
TrafficLight.Yellow => "准备",
TrafficLight.Green => "行",
_ => throw new ArgumentException()
};
// 元组 switch
string classify(int x, int y) => (x, y) switch
{
(0, 0) => "原点",
(_, 0) => "x 轴",
(0, _) => "y 轴",
(_, _) => "其他"
};对比传统 switch 语句,优势巨大:
- 简洁:一行一个分支,没有 break 噪音。
- 表达式:能直接赋值或 return。
- 模式强大:关系模式
>= 90、元组模式(0, _)、属性模式{ Length: > 0 }。 - 编译器检查:有
_兜底才不警告,避免漏分支。
实际开发中,90% 的多分支场景应该用 switch 表达式,传统 switch 语句留给"分支里要做很多事"的场景。
四、for 循环
知道循环次数时用 for:
// for 循环:知道次数时用
for (int i = 0; i < 5; i++)
{
Console.WriteLine($"第 {i + 1} 次");
}
// 输出 第 1 次 ... 第 5 次
// 倒序
for (int i = 10; i > 0; i--)
Console.WriteLine(i);
// 步长为 2
for (int i = 0; i < 20; i += 2)
Console.WriteLine(i); // 0 2 4 ... 18
// 嵌套循环(九九乘法表)
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= i; j++)
Console.Write($"{j}×{i}={i * j}\t");
Console.WriteLine();
}for 的三段(初始化、条件、迭代)都是可选的,for (;;) 是无限循环(等价 while (true))。
五、foreach 循环(C# 推荐)
遍历集合优先用 foreach,比 for 简洁,不易错:
// foreach:遍历集合,最简洁
string[] fruits = { "苹果", "香蕉", "橙子" };
foreach (var f in fruits)
Console.WriteLine(f);
// 遍历 List
var nums = new List<int> { 10, 20, 30 };
foreach (int n in nums)
Console.WriteLine(n);
// 遍历字典
var dict = new Dictionary<string, int>
{
["apple"] = 5,
["banana"] = 3
};
foreach (var kv in dict)
Console.WriteLine($"{kv.Key}: {kv.Value}");
// 遍历字符串(字符序列)
foreach (char c in "Hello")
Console.Write(c + " "); // H e l l oforeach 适用于所有 IEnumerable 集合(数组、List、Dictionary、字符串等)。需要索引时再用 for。
六、while 与 do-while
不知道循环次数、根据条件决定时用 while:
// while:条件成立时执行
int n = 5;
while (n > 0)
{
Console.WriteLine(n);
n--;
}
// do-while:先执行一次再判断
int i = 0;
do
{
Console.WriteLine(i);
i++;
} while (i < 5);
// 经典:读用户输入直到合法
string input;
do
{
Console.Write("请输入 yes 或 no:");
input = Console.ReadLine();
} while (input != "yes" && input != "no");区别:
while:先判断后执行,可能一次都不执行。do-while:先执行后判断,至少执行一次。适合"至少做一次"的场景,如读用户输入直到合法。
七、break、continue、return
// break:跳出整个循环
for (int i = 0; i < 100; i++)
{
if (i == 5)
break; // i=5 时整个循环结束
Console.WriteLine(i); // 0 1 2 3 4
}
// continue:跳过本次,继续下一次
for (int i = 0; i < 10; i++)
{
if (i % 2 == 0)
continue; // 偶数跳过
Console.WriteLine(i); // 1 3 5 7 9
}
// 嵌套循环用 break 只能跳出内层
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (j == 1) break; // 只跳出内层
}
}
// goto 跳出多层(罕见但有时清晰)
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (i + j > 3)
goto outer; // 直接跳出所有
}
}
outer:
Console.WriteLine("跳出");区别:
break:跳出最近一层循环。continue:跳过本次,继续下一次。return:直接退出整个方法(更强力)。goto 标签:跳出多层。少用,但跳出多重循环时偶尔清晰。
建议:能用 return/continue 简化就别用 break;别用 goto 除非跳出多层。
八、C# 特有:foreach 与 LINQ 联动
C# 的 foreach 配合 LINQ 能写出非常声明式的代码:
// 传统 for 循环写法
int[] nums = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var evens = new List<int>();
foreach (int n in nums)
{
if (n % 2 == 0)
evens.Add(n);
}
// LINQ + foreach(声明式)
var evens2 = nums.Where(n => n % 2 == 0);
foreach (int n in evens2)
Console.WriteLine(n);这只是一个引子,LINQ 后面会单独一篇讲。
九、常见陷阱
- foreach 中修改集合:会抛
InvalidOperationException。要修改先.ToList()。 - for 循环边界:注意
<vs<=,差一个就是越界。 - 死循环:忘记
i++会让 for 永不退出。检查循环条件最终能否变 false。 - switch 漏 default:新增枚举值时容易漏分支。switch 表达式 + 弃元更安全。
- 浮点循环:
for (double d = 0; d != 1.0; d += 0.1)可能死循环(精度问题)。用 int 计数。
小结
控制流是编程的肌肉记忆,语法不难但写好需要练习。记住现代 C# 的写法偏好:多分支用 switch 表达式、遍历集合用 foreach、判空用 is null、避免冗余 == true。下一篇我们看 C# 的方法——把代码组织成可复用的单元。
← 上一篇 C# 运算符
下一篇 C# 方法 →