1. 程式人生 > >C# 8.0中的模式匹配

C# 8.0中的模式匹配

條件 ges round opera sha 一個 bsp rop tran

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的模式匹配有了進一步的增強,雖然可以又有人要說是語法糖了,但用得好的話可以讓你的代碼邏輯簡化不少,更加容易理解。

參考文章

Do more with patterns in C# 8.0

C# 8.0中的模式匹配