Skip to content

07-条件判断

条件判断是编程中非常重要的逻辑控制手段,用于根据不同的条件执行不同的代码。C# 提供了多种条件判断方式。


一、if-else 语句

基本语法

csharp
if (条件)
{
    // 条件为 true 时执行
}
else if (其他条件)
{
    // 其他条件为 true 时执行
}
else
{
    // 所有条件都不满足时执行
}

示例

csharp
int score = 85;

if (score >= 90)
    Console.WriteLine("优秀");
else if (score >= 80)
    Console.WriteLine("良好");
else if (score >= 60)
    Console.WriteLine("及格");
else
    Console.WriteLine("不及格");

注意: 当代码块只有一行时,可以省略花括号,但不推荐(容易出错)。

嵌套 if

csharp
int number = 15;

if (number > 0)
{
    if (number % 2 == 0)
        Console.WriteLine("正偶数");
    else
        Console.WriteLine("正奇数");
}

避免嵌套过深(超过 3 层),考虑使用 switch 或提前 return。


二、switch 语句

传统 switch

csharp
int day = 3;
string dayName;

switch (day)
{
    case 1:
        dayName = "星期一";
        break;
    case 2:
        dayName = "星期二";
        break;
    case 3:
        dayName = "星期三";
        break;
    case 4:
        dayName = "星期四";
        break;
    case 5:
        dayName = "星期五";
        break;
    case 6:
    case 7:
        dayName = "周末";
        break;
    default:
        dayName = "无效的星期";
        break;
}

Console.WriteLine(dayName);  // 星期三

switch 的注意事项

  • 每个 case 必须以 breakreturnthrowgoto 结束
  • C# 不支持 case 穿透(fall-through),除非 case 为空(多个 case 共享代码)
  • default 是可选的

三、switch 表达式(C# 8.0+)

switch 表达式是 switch 语句的更简洁的表达式版本。

csharp
// 传统 switch 语句
string GetGrade(int score)
{
    switch (score)
    {
        case >= 90: return "优秀";
        case >= 80: return "良好";
        case >= 60: return "及格";
        default: return "不及格";
    }
}

// switch 表达式(简洁!)
string GetGrade2(int score) => score switch
{
    >= 90 => "优秀",
    >= 80 => "良好",
    >= 60 => "及格",
    _ => "不及格"       // _ 相当于 default
};

// 多条件匹配
string Describe(object obj) => obj switch
{
    int i when i > 0 => $"正数:{i}",
    int i when i < 0 => $"负数:{i}",
    int i => "零",
    string s => $"字符串:{s}",
    null => "null",
    _ => $"其他类型:{obj.GetType().Name}"
};

switch 表达式 vs switch 语句

对比项switch 语句switch 表达式
语法switch + case表达式 switch { }
返回值需要手动赋值或 return直接返回结果
case 关键字需要不需要
defaultdefault:_ =>
简洁性冗长简洁
模式匹配支持支持丰富模式

四、模式匹配(Pattern Matching)

C# 7.0+ 引入了强大的模式匹配功能。

1. 类型模式

csharp
object obj = "Hello";

// 传统方式
if (obj is string)
{
    string s = (string)obj;
    Console.WriteLine(s.Length);
}

// 模式匹配:检查 + 转换一步到位
if (obj is string s)
{
    Console.WriteLine(s.Length);  // ✅ 直接使用 s
}

// 取反模式(C# 9.0+)
if (obj is not int)
{
    Console.WriteLine("不是整数");
}

2. 属性模式

csharp
class Point
{
    public int X { get; set; }
    public int Y { get; set; }
}

string DescribePoint(Point p) => p switch
{
    { X: 0, Y: 0 } => "原点",
    { X: 0 } => "Y 轴上",
    { Y: 0 } => "X 轴上",
    _ => $"({p.X}, {p.Y})"
};

3. 元组模式

csharp
// 石头剪刀布
string RockPaperScissors(string player1, string player2) =>
    (player1, player2) switch
    {
        ("石头", "剪刀") => "玩家1 获胜",
        ("剪刀", "布") => "玩家1 获胜",
        ("布", "石头") => "玩家1 获胜",
        _ when player1 == player2 => "平局",
        _ => "玩家2 获胜"
    };

Console.WriteLine(RockPaperScissors("石头", "剪刀"));  // 玩家1 获胜

五、三元运算符

简洁的条件判断表达式,返回一个值。

csharp
// 语法:条件 ? 为真时 : 为假时

int number = 10;
string result = number > 0 ? "正数" : "非正数";
Console.WriteLine(result);  // 正数

// 嵌套三元(可读性差,不推荐)
string status = number > 0 ? "正数" : number < 0 ? "负数" : "零";

// 推荐:用 if-else 代替嵌套三元
string GetStatus(int n)
{
    if (n > 0) return "正数";
    if (n < 0) return "负数";
    return "零";
}

六、空值处理运算符

1. 空合并运算符 ??

csharp
string? name = null;
string display = name ?? "未知用户";  // name 为 null 时使用默认值
Console.WriteLine(display);  // 未知用户

// 链式使用
string? a = null, b = null, c = "Hello";
string result = a ?? b ?? c ?? "全部为 null";
Console.WriteLine(result);  // Hello

// ??= 赋值(C# 8.0+)
string? text = null;
text ??= "默认值";  // text 为 null 时赋值
Console.WriteLine(text);  // 默认值

2. 空条件运算符 ?.

csharp
class Person
{
    public string? Name { get; set; }
    public Address? Address { get; set; }
}

class Address
{
    public string? City { get; set; }
}

Person? person = null;

// 安全访问成员——任一环节为 null 则结果为 null
string? city = person?.Address?.City ?? "未知城市";
Console.WriteLine(city);  // 未知城市

// 安全调用方法
Action? action = null;
action?.Invoke();  // action 为 null 时不执行,不抛异常

// 安全访问数组元素
int[]? numbers = null;
int? first = numbers?[0];  // null,而不是异常

3. 空值运算符对比

运算符名称用途示例
??空合并左侧为 null 时返回右侧name ?? "默认"
??=空合并赋值左侧为 null 时赋值name ??= "默认"
?.空条件安全访问成员person?.Name
?[i]空条件索引安全访问索引arr?[0]

七、条件判断方式选择指南

场景推荐方式示例
2-3 个分支,较简单if-else成绩等级判断
多个固定值匹配switch 或 switch 表达式星期、状态码
类型检查和转换模式匹配 isobj is string s
简单二选一返回值三元运算符a > b ? a : b
null 默认值?? 运算符name ?? "默认"
安全访问成员?. 运算符person?.Name

八、综合案例:订单折扣系统

csharp
public class Order
{
    public decimal Amount { get; set; }
    public string CustomerType { get; set; }  // "普通", "VIP", "企业"
    public int YearsAsCustomer { get; set; }
    public bool IsHoliday { get; set; }
}

// 使用多种条件判断方式
static decimal CalculateDiscount(Order order)
{
    // 空值检查
    if (order == null)
        throw new ArgumentNullException(nameof(order));

    // 基础折扣——使用 switch 表达式
    decimal baseDiscount = order.CustomerType switch
    {
        "VIP" => 0.15m,
        "企业" => 0.10m,
        "普通" => 0.05m,
        _ => 0m
    };

    // 老客户额外折扣——使用三元
    decimal loyaltyDiscount = order.YearsAsCustomer > 5 ? 0.05m : 0m;

    // 节假日折扣——使用 if
    decimal holidayDiscount = 0;
    if (order.IsHoliday && order.Amount > 100)
    {
        holidayDiscount = 0.03m;
    }

    // 总折扣(不超过 30%)——使用 ?? 确保不会有 null
    decimal totalDiscount = Math.Min(baseDiscount + loyaltyDiscount + holidayDiscount, 0.30m);

    return order.Amount * totalDiscount;
}

// 使用
var order = new Order
{
    Amount = 1000,
    CustomerType = "VIP",
    YearsAsCustomer = 6,
    IsHoliday = true
};

decimal discount = CalculateDiscount(order);
Console.WriteLine($"折扣金额:{discount:C}");  // 折扣金额:230.00

核心知识点总结

条件判断方式对比

方式适用场景返回值可读性
if-else任何条件判断
switch 语句多固定值匹配一般
switch 表达式多条件返回结果有返回值
三元运算符简单二选一有返回值简洁
?? / ?.空值处理有返回值简洁

注意事项

  1. if-else 条件必须是 bool 类型——C# 不允许 if (1) 这样的写法
  2. switch 的每个 case 需要 break——不像 C++ 可以穿透
  3. 三元运算符不要嵌套——超过一层应使用 if-else
  4. ?. 和 ?? 配合使用——实现安全的空值处理链
  5. switch 表达式是表达式不是语句——必须有返回值,所有情况都要覆盖
  6. 模式匹配使代码更简洁——优先使用 is 模式匹配替代 is + 强制转换
  7. 避免深层嵌套——超过 3 层应考虑重构

Released under the MIT License.