ZetCode

C# switch 表达式

上次修改时间:2024 年 1 月 19 日

在本文中,我们将展示如何在 C# 中使用 switch 表达式。

Switch 表达式 是对经典 switch 语句 的强大增强。它们由多个分支组成,每个分支都返回一个值。

分支可以评估以下内容:

C# switch 表达式值模式

使用值模式,switch 分支基于常量值,例如整数或字符串。

Program.cs
Console.Write("Enter a domain name: ");

string? domain = Console.ReadLine();

domain = domain?.Trim().ToLower();

string result = domain switch
{
    "us" => "United States",
    "de" => "Germany",
    "sk" => "Slovakia",
    "hu" => "Hungary",

    _ => "Unknown"
};

Console.WriteLine(result);

在该示例中,我们使用 switch 表达式将国家/地区名称映射到其域名。

$ dotnet run
Enter a domain name: sk
Slovakia
# dotnet run
Enter a domain name: jp
Unknown

C# switch 表达式类型模式

数据类型可以是 switch 表达式的模式。

Program.cs
int age = 23;
string name = "Peter";

List<string> colors = ["blue", "khaki", "orange"];
int[] nums = [1, 2, 3, 4, 5];

Console.WriteLine(check(age));
Console.WriteLine(check(name));
Console.WriteLine(check(colors));
Console.WriteLine(check(nums));

object check(object val) => val switch
{
    int => "integer",
    string => "string",
    List<string> => "list of strings",
    Array => "array",
    _ => "unknown"
};

在该示例中,我们使用 switch 表达式找出变量的数据类型。

$ dotnet run
integer
string
list of strings
array

C# switch 表达式关系模式

可以使用关系模式构建强大的逻辑。

Program.cs
List<int> nums = [-3, 2, 0, 1, 9, -2, 7];

foreach (var num in nums)
{
    var res = num switch
    {
        < 0 => "negative",
        0 => "zero",
        > 0 => "positive"
    };

    Console.WriteLine($"{num} is {res}");
}

我们有一个整数列表。在 foreach 循环中,我们遍历列表并使用 switch 表达式打印该值是负数、正数还是零。在 switch 表达式内部,我们使用简单的关系表达式。

$ dotnet run
-3 is negative
2 is positive
0 is zero
1 is positive
9 is positive
-2 is negative
7 is positive

C# switch 表达式 when 守卫

使用 when 守卫为我们的表达式分支增加了一些额外的灵活性。

Program.cs
List<User> users =
[
    new ("John", "Doe", 34),
    new ("Roger", "Roe", 44),
    new ("Jane", "Doe", 44),
    new ("Robert", "Molnar", 41),
    new ("Lucia", "Petrovicova", 16),
];

foreach (var user in users)
{
    Console.WriteLine(checkPerson(user));
}

string checkPerson(User u)
{
    return u switch
    {
        { LastName: "Doe" } => "Doe family",
        { Age: var age } when age < 18 => "minor person",
        _ => $"{u}"
    };
}

record User(string FirstName, string LastName, int Age);

在该示例中,我们使用 when 守卫来考虑 18 岁以下的用户。

$ dotnet run
Doe family
User { FirstName = Roger, LastName = Roe, Age = 44 }
Doe family
User { FirstName = Robert, LastName = Molnar, Age = 41 }
minor person

C# switch 表达式逻辑模式

andor 运算符可以在 switch 表达式中使用。

Program.cs
List<User> users =
[
    new ("Peter Novak", "driver", new DateTime(2000, 12, 1)),
    new ("John Doe", "gardener", new DateTime(1996, 2, 10)),
    new ("Roger Roe", "teacher", new DateTime(1976, 5, 9)),
    new ("Lucia Smith", "student", new DateTime(2007, 8, 18)),
    new ("Roman Green", "retired", new DateTime(1945, 7, 21)),
];

foreach (var user in users)
{
    int age = GetAge(user);

    string res = age switch
    {
        > 65 => "senior",
        >= 18 and <= 64 => "adult",
        < 18 => "minor",
        _ => "unknown",
    };

    Console.WriteLine($"{user.Name} is {res}");
}

int GetAge(User user)
{
    return (int)Math.Floor((DateTime.Now - user.Dob).TotalDays / 365.25D);
}

record User(string Name, string Occupation, DateTime Dob);

逻辑 and 运算符用于将 adult 字符串分配给年龄在 18 到 65 岁之间的用户。

$ dotnet run
Peter Novak is adult
John Doe is adult
Roger Roe is adult
Lucia Smith is minor
Roman Green is senior

在以下示例中,我们有一个 or 表达式。

Program.cs
var q = @"
WWI started in:

1) 1912
2) 1914
3) 1918
";

Console.WriteLine(q);

var inp = Console.ReadLine();
var ans = int.Parse(inp.Trim());

var res = ans switch
{
    1 or 3 => "Incorrect",
    2 => "correct",
    _ => "unknown option"
};

Console.WriteLine(res);

该示例检查用户的输入,并在 switch 表达式中使用 or 表达式。

C# switch 表达式属性模式

对象属性的值可以是 switch 表达式中的模式。

Program.cs
List<Product> products =
[
    new ("Product A", 70m, 1, 10),
    new ("Product B", 50m, 3, 15),
    new ("Product C", 35m, 2, 20)
];

foreach (var product in products)
{
    decimal sum = product switch
    {
        Product { Quantity: 2 } =>
                product.Price * product.Quantity * (1 - product.Discount / 100m),
        _ => product.Price * product.Quantity,
    };

    Console.WriteLine($"The final sum for {product.Name} is {sum}");
}

record Product(string Name, decimal Price, int Quantity, int Discount);

在该示例中,如果我们购买了该产品的两个商品,则将折扣应用于该产品的价格。

$ dotnet run
The final sum for Product A is 70
The final sum for Product B is 150
The final sum for Product C is 56.0

已将 20% 的折扣应用于产品 C。

C# switch 表达式元组模式

switch 表达式可以使用元组模式。

Program.cs
while (true)
{
    var menu = "Select: \n1 -> rock\n2 -> paper\n3 -> scissors\n4 -> finish";
    Console.WriteLine(menu);

    string[] options = {"rock", "paper", "scissors"};

    int val;

    try {

        var line = Console.ReadLine();
        if (string.IsNullOrEmpty(line))
        {
            Console.WriteLine("Invalid choice");
            continue;
        }

        val = int.Parse(line);
    } catch (FormatException)
    {
        Console.WriteLine("Invalid choice");
        continue;
    }

    if (val == 4)
    {
        break;
    }

    if (val < 1 || val > 4)
    {
        Console.WriteLine("Invalid choice");
        continue;
    }

    string human = options[val-1];

    var rnd = new Random();
    int n = rnd.Next(0, 3);

    string computer = options[n];

    Console.WriteLine($"I have {computer}, you have {human}");

    var res = RockPaperScissors(human, computer);

    Console.WriteLine(res);
}

Console.WriteLine("game finished");


string RockPaperScissors(string human, string computer) => (human, computer) switch
{
    ("rock", "paper") => "Rock is covered by paper. You loose",
    ("rock", "scissors") => "Rock breaks scissors. You win.",
    ("paper", "rock") => "Paper covers rock. You win.",
    ("paper", "scissors") => "Paper is cut by scissors. You loose.",
    ("scissors", "rock") => "Scissors are broken by rock. You loose.",
    ("scissors", "paper") => "Scissors cut paper. You win.",
    (_, _) => "tie"
};

我们有一个石头剪刀布游戏,在其中我们利用元组表达式。

string RockPaperScissors(string human, string computer) => (human, computer) switch
{
    ("rock", "paper") => "Rock is covered by paper. You loose",
    ("rock", "scissors") => "Rock breaks scissors. You win.",
...

从人类和计算机的选择中,我们形成元组,这些元组用作 switch 表达式中的模式,以得出游戏结论。

$ dotnet run
Select:
1 -> rock
2 -> paper
3 -> scissors
4 -> finish
1
I have rock, you have rock
tie
Select:
1 -> rock
2 -> paper
3 -> scissors
4 -> finish
2
I have paper, you have paper
tie
Select:
1 -> rock
2 -> paper
3 -> scissors
4 -> finish
3
I have paper, you have scissors
Scissors cut paper. You win.
Select:
1 -> rock
2 -> paper
3 -> scissors
4 -> finish
4
game finished

列表模式

自 C# 11 以来,switch 表达式分支可以评估列表模式。

Program.cs
List<Student> students = [
    new ("John", ['a', 'b', 'a', 'c', 'd', 'd', 'e']),
    new ("Lucia", ['b', 'b', 'c', 'c', 'a', 'e', 'e']),
    new ("Paul", ['a', 'b', 'a', 'c', 'b', 'e', 'e']),
    new ("Roger", ['a', 'c', 'c', 'c', 'a', 'b', 'e']),
    new ("Michal", ['b', 'b', 'c', 'c', 'a', 'e', 'e']),
];

foreach (var student in students)
{
    string res = student.Answers switch
    {
        ['b', 'b', 'c', 'c', 'a', 'e', 'e'] => $"{student.Name} has passed",
        _ => $"{student.Name} has failed"
    };

    Console.WriteLine(res);
}

record Student(string Name, List<char> Answers);

学生正在进行包含七个问题的测试。 这些问题的答案为“a”到“e”。 要通过测试,必须正确回答所有问题。

List<Student> students = [
    new ("John", ['a', 'b', 'a', 'c', 'd', 'd', 'e']),
    new ("Lucia", ['b', 'b', 'c', 'c', 'a', 'e', 'e']),
    new ("Paul", ['a', 'b', 'a', 'c', 'b', 'e', 'e']),
    new ("Roger", ['a', 'c', 'c', 'c', 'a', 'b', 'e']),
    new ("Michal", ['b', 'b', 'c', 'c', 'a', 'e', 'e']),
];

这是学生及其测试答案的列表。

string res = student.Answers switch
{
    ['b', 'b', 'c', 'c', 'a', 'e', 'e'] => $"{student.Name} has passed",
    _ => $"{student.Name} has failed"
};

我们根据正确答案检查结果。 该模式是一个字符列表,代表正确的答案。

$ dotnet run
John has failed
Lucia has passed
Paul has failed
Roger has failed
Michal has passed

来源

switch 表达式 - 使用 switch 关键字的模式匹配表达式

在本文中,我们介绍了 C# switch 表达式。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。 我从 2007 年开始撰写编程文章。到目前为止,我已经撰写了 1,400 多篇文章和 8 本电子书。 我拥有超过十年的编程教学经验。

列出所有 C# 教程