C# 8.0中的模式匹配
C# 8.0中的模式匹配相對C# 7.0來說有了進一步的增強,對於如下類:
class
Point
{
public
int
X
{
get
; }
public
int
Y
{
get
; }
public
Point
(
int
x
,
int
y
) => (
X
,
Y
) = (
x
,
y
);
public
void
Deconstruct
(
out
int
x
,
out
int
y
) => (
x
,
y
) = (
X
,
Y
);
}
首先來看C# 7.0中一個經典的模式匹配示例:
static string Display(object o)
{
switch (o)
{
case Point p when p.X == 0 && p.Y == 0:
return "origin";
case Point p:
return $"({p.X}, {p.Y})";
default:
return "unknown";
}
}
在C# 8.0中,它有更加精簡的寫法。
Switch表示式
在C# 8.0中,可以利用新的switch方式成模式匹配:
static string Display(object o) => o switch
{
Point p when p.X == 0 && p.Y == 0 => "origin",
Point p=> $"({p.X}, {p.Y})",
_=> "unknown"
};
它利用一條switch語句完成了模式匹配,第一樣看上去要簡潔一些。不過,它還有更多更簡單的寫法。
Property patterns
可以直接通過在屬性上指定值作為判定條件,
static string Display(object o) => o switch
{
Point { X: 0, Y: 0 } => "origin",
Point p=> $"({p.X}, {p.Y})",
_=> "unknown"
};
也可以將屬性值傳遞出來。
static string Display(object o) => o switch
{
Point { X: 0, Y: 0 }=> "origin",
Point { X: var x, Y: var y } => $"({x}, {y})",
_=> "unknown"
};
Positional patterns
利用解構函式 ,可以寫出更加精簡的表示式。
static string Display(object o) => o switch
{
Point(0, 0)=> "origin",
Point(var x, var y) => $"({x}, {y})",
_=> "unknown"
};
如果沒有型別轉換,則可以寫得更加簡單了:
static string Display(Point o) => o switch
{
(0, 0)=> "origin",
(var x, var y) => $"({x}, {y})"
};
非空判斷
如果只是判斷空和非空,則有最簡單的模式:
{ }=> o.ToString(), null => "null"
Tuple patterns
也支援直接對ValueTuple進行模式匹配,用起來非常靈活。
static State ChangeState(State current, Transition transition, bool hasKey) =>
(current, transition, hasKey) switch
{
(Opened, Close, _)=> Closed,
(Closed, Open,_)=> Opened,
(Closed, Lock, true)=> Locked,
(Locked, Unlock, true) => Closed,
_ => throw new InvalidOperationException($"Invalid transition")
};
小結
C# 8.0的模式匹配有了進一步的增強,雖然可以又有人要說是語法糖了,但用得好的話可以讓你的程式碼邏輯簡化不少,更加容易理解。