C#的switch的用法及模式匹配 绝对的经典的语法糖
switch-case语句经常被认为是if-else语句的替代品,但是在众多程序语言中还是能见到switch的存在,这很大程度上是因为switch更实用,这一点在C#中更能提现。
简单的语法就不说了,一个简单的switch用法:
switch (cmd)
{
case "start": Console.WriteLine("start"); break;
case "pause": Console.WriteLine("pause"); break;
case "stop": Console.WriteLine("stop"); break;
default: Console.WriteLine("invalid commond"); break;
}
注意,C#规定,各个case语句不允许贯穿,也就是说每个case语句执行完之后,必须显示的退出,比如使用break、goto、return、throw等语句退出,但是C#又允许你使用goto case、goto default语句来实现贯穿(注意使用,避免造成死循环):
string color = "blue";
switch (color)
{
case "red": Console.WriteLine("red"); goto default;
case "green": Console.WriteLine("green"); goto case "red";
case "blue": Console.WriteLine("blue"); goto case "green";
default: Console.WriteLine("default"); break;
}
//输出:
//blue
//green
//red
//default
虽然C#中switch不允许case贯穿,但是运行多个case语句组合:
switch (dayOfWeek)
{
case DayOfWeek.Monday: Console.WriteLine("weekend"); break;
case DayOfWeek.Tuesday: Console.WriteLine("weekend"); break;
case DayOfWeek.Wednesday: Console.WriteLine("weekend"); break;
case DayOfWeek.Thursday: Console.WriteLine("weekend"); break;
case DayOfWeek.Friday: Console.WriteLine("weekend"); break;
case DayOfWeek.Saturday:
case DayOfWeek.Sunday: Console.WriteLine("weekend"); break;
}
C# 6.0及之前版本的switch中,匹配表达式只支持字符串、字符、整形(如int、long等)、bool、枚举几个类型,因此switch的作用很有限,被认为是if-else的替代品也不无道理。
C#7.0之后,switch的限制得到放宽,每个case语句不在是一个常量,而是一个模式,更多关于模式内容见:C#中的模式匹配
看看一些简单的使用例子:
1、声明模式
public void ShowMessage(object value)
{
switch (value)
{
case int i: Console.WriteLine($"value is int:{i}"); break;
case long l: Console.WriteLine($"value is long:{l}"); break;
case bool b: Console.WriteLine($"value is bool:{b}"); break;
case string s: Console.WriteLine($"value is string:{s}"); break;
default: Console.WriteLine($"value is object"); break;
}
}
2、类型模式
类型模式可以理解为在声明模式中使用了弃元:
public void ShowMessage(object value)
{
switch (value)
{
case int: Console.WriteLine($"value is int"); break;
case long: Console.WriteLine($"value is long"); break;
case bool: Console.WriteLine($"value is bool"); break;
case string: Console.WriteLine($"value is string"); break;
default: Console.WriteLine($"value is object"); break;
}
}
3、常量模式
常量模式可以理解为原来C#6.0及之前的用法:
switch (score)
{
case 10:
case 9: Console.WriteLine("excellent"); break;
case 8: Console.WriteLine("good"); break;
case 7:
case 6: Console.WriteLine("fair"); break;
default: Console.WriteLine("poor"); break;
}
4、关系模式
switch (score)
{
case >= 80: Console.WriteLine("excellent"); break;
case >= 60: Console.WriteLine("good"); break;
default: Console.WriteLine("poor"); break;
}
5、逻辑模式
switch (value)
{
case 0: Console.WriteLine("value is 0"); break;
case not 0 and (100 or -100): Console.WriteLine("abs(value)==100"); break;
case not 0 and (> 0 and < 100): Console.WriteLine("value is positive and less than 100"); break;
case not 0 and > 0: Console.WriteLine("value is positive and greater than 100"); break;
case < -100 or (< 0 and > -100): Console.WriteLine("value is negative and not equals -100"); break;
}
6、属性模式
switch (time)
{
case { Year: 2020 or 2021, Month: <= 6, Day: 1 } t: Console.WriteLine($"the first day of every month in the first half of 2020 and 2021"); break;
case { Year: not 2022 }: Console.WriteLine($"not 2022"); break;
case { DayOfWeek: not DayOfWeek.Sunday and not DayOfWeek.Saturday }: Console.WriteLine($"recursion"); break;
}
7、位置模式
位置模式采用解构的特性来说明指定的模式是否匹配:
public record Point2D(int X, int Y);//记录可以解构
static void Print(Point2D point)
{
switch (point)
{
case ( > 0, > 0): Console.WriteLine("first quadrant"); break;
case ( < 0, > 0): Console.WriteLine("second quadrant"); break;
case ( < 0, < 0): Console.WriteLine("third quadrant"); break;
case ( > 0, < 0): Console.WriteLine("fourth quadrant"); break;
default: Console.WriteLine("coordinate axis"); break;
}
}
8、Var模式
Var模式往往和属性模式和位置模式结合,用于提取属性变量值:
switch (point)
{
case (var x, var y, var z): Console.WriteLine($"3D point:({x},{y},{z})"); break;//在位置模式中使用
case Point2D { X: var x, Y: var y }: Console.WriteLine($"2D point:({x},{y})"); break;//在属性模式中使用
default: Console.WriteLine("others"); break;
}
9、弃元模式
弃元模式在switch语句中用的不多,但是在switch表达式中使用的多:
var result = score switch
{
>= 80 => "excellent",
>= 60 => "good",
_ => "poor" //弃元在switch表达式中就相当于default
};
switch表达式
从C#8.0开始,switch有了一种新的用法:switch表达式,它的主要就是类似于sql语句中的case-when的用法,可以方便的进行匹配输出,格式:
var_name switch
{
match_expr1 => value1,
match_expr2 => value2,
match_expr3 => value3,
_ => default_value
}
这里的每一个 match_expr 是一个匹配模式,相当于switch语句中的case语句的模式内容,它的含义就是,如果match_expr模式匹配成功,那么就返回对应的值,需要注意的是,switch表达式是输出语句!
比如之前有这样的一个枚举:
public enum Color
{
Unknown,
Red,
Blue,
Green
}
使用中我们可能会需要进行一些转换,可能会用到 if 判断:
static string Convert(Color color)
{
string rbg;
if (color == Color.Red)
{
rbg = "#FF0000";
}
else if (color == Color.Blue)
{
rbg = "#0000FF";
}
else if (color == Color.Green)
{
rbg = "#00FF00";
}
else
{
rbg = "";
}
return rbg;
}
或者使用switch语句:
static string Convert(Color color)
{
string rbg;
switch (color)
{
case Color.Red:rbg = "#FF0000";break;
case Color.Blue: rbg = "#0000FF"; break;
case Color.Green: rbg = "#00FF00"; break;
default: rbg = ""; break;
}
return rbg;
}
现在使用switch表达式可简写Convert方法:
static string Convert(Color color)
{
return color switch
{
Color.Red => "this is red",
Color.Blue => "this is blue",
Color.Green => "this is green",
_ => "",
};
}
这样看起简洁密聊了许多。
case-when
无论是在switch语句中,还是在switch表达式中,在模式匹配之后,我们可以跟着一个when语句,对匹配结果做进一步的判断:
比如一些简单的例子:
static string Convert(object color)
{
return color switch
{
Color c when c == Color.Red => "red",
Color c when c == Color.Blue => "blue",
Color c when c == Color.Green => "green",
_ => "unknown color",
};
}
再比如:
var desc = shape switch
{
Point p when p.IsEmpty => "empty point",
Point { X: var x, Y: var y } when object.Equals(x, y) => "point:x=y",
Point => $"point",
Rectangle { Width: var width, Height: var height } when width == height => "square",
Rectangle => "rectangle",
_ => "other shape"
};
when语句弥补了模式的一些不足,可以让判断更加精确而不用我们自己在后续代码中使用if语句进行判断。
出处:https://www.cnblogs.com/shanfeng1000/p/14951498.html
=======================================================================================
关于C#8.0的SwitchCaseWhen的用法
switch case when
8.0新特性,把贼好用!(熟悉T-SQL的会感觉很亲切,新的switch扩展变得和T-SQL的Case When Then End类似,可以支持不等式区间的布尔表达式) ,其可读性吊锤if else!
语法
switch (fileName)
{
case string s when s.Contains(".xsd"): // or EndsWith, etc
// todo
break;
default:
break;
}
示例测试程序:
class Person
{
public int grade { get; set; }
public string name { get; set; }
public string level { get; set; }
}
IList<Person> persons= new List<Person>()
{
new Person{ grade = 50, name = "A_People", level = "None" },
new Person{ grade = 70, name = "B_People", level = "None" },
new Person{ grade = 91, name = "C_People", level = "None" }
};
foreach (Person p in persons)
{
switch (p)
{
case Person obj when obj.grade < 60:
{
obj.level = "不及格";
break;
}
case Person obj when obj.grade > 60 && obj.grade <= 70:
{
obj.level = "及格";
break;
}
case Person obj when obj.grade > 60 && obj.grade <= 70:
{
obj.level = "良好";
break;
}
case Person obj when obj.grade >= 90:
{
obj.level = "优秀";
break;
}
default:
{
Person.level = "None";
break;
}
}
Console.WriteLine($"此人的:{p.name} 成绩:{p.level}");


浙公网安备 33010602011771号