溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

C#模式匹配有哪些及怎么實現(xiàn)

發(fā)布時間:2022-03-04 16:03:17 來源:億速云 閱讀:94 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“C#模式匹配有哪些及怎么實現(xiàn)”,在日常操作中,相信很多人在C#模式匹配有哪些及怎么實現(xiàn)問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C#模式匹配有哪些及怎么實現(xiàn)”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

模式匹配

要使用模式匹配,首先要了解什么是模式。在使用正則表達(dá)式匹配字符串時,正則表達(dá)式自己就是一個模式,而對字符串使用這段正則表達(dá)式進(jìn)行匹配的過程就是模式匹配。而在代碼中也是同樣的,我們對對象采用某種模式進(jìn)行匹配的過程就是模式匹配。

C# 11 支持的模式有很多,包含:

  • 聲明模式(declaration pattern)

  • 類型模式(type pattern)

  • 常數(shù)模式(constant pattern)

  • 關(guān)系模式(relational pattern)

  • 邏輯模式(logical pattern)

  • 屬性模式(property pattern)

  • 位置模式(positional pattern)

  • var 模式(var pattern)

  • 丟棄模式(discard pattern)

  • 列表模式(list pattern)

  • 切片模式(slice pattern)

而其中,不少模式都支持遞歸,也就意味著可以模式嵌套模式,以此來實現(xiàn)更加強大的匹配功能。

模式匹配可以通過 switch 表達(dá)式來使用,也可以在普通的 switch 語句中作為 case 使用,還可以在 if 條件中通過 is 來使用。本文主要在 switch 表達(dá)式中使用模式匹配。

那么接下來就對這些模式進(jìn)行介紹。

實例:表達(dá)式計算器

為了更直觀地介紹模式匹配,我們接下來利用模式匹配來編寫一個表達(dá)式計算器。

為了編寫表達(dá)式計算器,首先我們需要對表達(dá)式進(jìn)行抽象:

public abstract partial class Expr<T> where T : IBinaryNumber<T>
{
    public abstract T Eval(params (string Name, T Value)[] args);
}

我們用上面這個 Expr<T> 來表示一個表達(dá)式,其中 T 是操作數(shù)的類型,然后進(jìn)一步將表達(dá)式分為常數(shù)表達(dá)式 ConstantExpr、參數(shù)表達(dá)式 ParameterExpr、一元表達(dá)式 UnaryExpr、二元表達(dá)式 BinaryExpr 和三元表達(dá)式 TernaryExpr。最后提供一個 Eval 方法,用來計算表達(dá)式的值,該方法可以傳入一個 args 來提供表達(dá)式計算所需要的參數(shù)。

有了一、二元表達(dá)式自然也需要運算符,例如加減乘除等,我們也同時定義 Operator 來表示運算符:

public abstract record Operator
{
    public record UnaryOperator(Operators Operator) : Operator;
    public record BinaryOperator(BinaryOperators Operator) : Operator;
}

然后設(shè)置允許的運算符,其中前三個是一元運算符,后面的是二元運算符:

public enum Operators
{
    [Description("~")] Inv, [Description("-")] Min, [Description("!")] LogicalNot,
    [Description("+")] Add, [Description("-")] Sub, [Description("*")] Mul, [Description("/")] Div,
    [Description("&")] And, [Description("|")] Or, [Description("^")] Xor,
    [Description("==")] Eq, [Description("!=")] Ne,
    [Description(">")] Gt, [Description("<")] Lt, [Description(">=")] Ge, [Description("<=")] Le,
    [Description("&&")] LogicalAnd, [Description("||")] LogicalOr,
}

你可以能會好奇對 T 的運算能如何實現(xiàn)邏輯與或非,關(guān)于這一點,我們直接使用 0 來代表 false,非 0 代表 true。

接下來就是分別實現(xiàn)各類表達(dá)式的時間!

常數(shù)表達(dá)式

常數(shù)表達(dá)式很簡單,它保存一個常數(shù)值,因此只需要在構(gòu)造方法中將用戶提供的值存儲下來。它的 Eval 實現(xiàn)也只需要簡單返回存儲的值即可:

public abstract partial class Expr<T> where T : IBinaryNumber<T>
{
    public class ConstantExpr : Expr<T>
    {
        public ConstantExpr(T value) => Value = value;

        public T Value { get; }
        public void Deconstruct(out T value) => value = Value;
        public override T Eval(params (string Name, T Value)[] args) => Value;
    }
}

參數(shù)表達(dá)式

參數(shù)表達(dá)式用來定義表達(dá)式計算過程中的參數(shù),允許用戶在對表達(dá)式執(zhí)行 Eval 計算結(jié)果的時候傳參,因此只需要存儲參數(shù)名。它的 Eval 實現(xiàn)需要根據(jù)參數(shù)名在 args 中找出對應(yīng)的參數(shù)值:

public abstract partial class Expr<T> where T : IBinaryNumber<T>
{
    public class ParameterExpr : Expr<T>
    {
        public ParameterExpr(string name) => Name = name;

        public string Name { get; }
        public void Deconstruct(out string name) => name = Name;
        // 對 args 進(jìn)行模式匹配
        public override T Eval(params (string Name, T Value)[] args) => args switch
        {
            // 如果 args 有至少一個元素,那我們把第一個元素拿出來存為 (name, value),
            // 然后判斷 name 是否和本參數(shù)表達(dá)式中存儲的參數(shù)名 Name 相同。
            // 如果相同則返回 value,否則用 args 除去第一個元素剩下的參數(shù)繼續(xù)匹配。
            [var (name, value), .. var tail] => name == Name ? value : Eval(tail),
            // 如果 args 是空列表,則說明在 args 中沒有找到名字和 Name 相同的參數(shù),拋出異常
            [] => throw new InvalidOperationException($"Expected an argument named {Name}.")
        };
    }
}

模式匹配會從上往下依次進(jìn)行匹配,直到匹配成功為止。

上面的代碼中你可能會好奇 [var (name, value), .. var tail] 是個什么模式,這個模式整體看是列表模式,并且列表模式內(nèi)組合使用聲明模式、位置模式和切片模式。例如:

  • []:匹配一個空列表。[1, _, 3]:匹配一個長度是 3,并且首尾元素分別是 1、3 的列表。其中 _ 是丟棄模式,表示任意元素。

  • [_, .., 3]:匹配一個末元素是 3,并且 3 不是首元素的列表。其中 .. 是切片模式,表示任意切片。

  • [1, ..var tail]:匹配一個首元素是 1 的列表,并且將除了首元素之外元素的切片賦值給 tail。其中 var tailvar 模式,用于將匹配結(jié)果賦值給變量。

  • [var head, ..var tail]:匹配一個列表,將它第一個元素賦值給 head,剩下元素的切片賦值給 tail,這個切片里可以沒有元素。

  • [var (name, value), ..var tail]:匹配一個列表,將它第一個元素賦值給 (name, value),剩下元素的切片賦值給 tail,這個切片里可以沒有元素。其中 (name, value) 是位置模式,用于將第一個元素的解構(gòu)結(jié)果根據(jù)位置分別賦值給 namevalue,也可以寫成 (var name, var value)。

一元表達(dá)式

一元表達(dá)式用來處理只有一個操作數(shù)的計算,例如非、取反等。

public abstract partial class Expr<T> where T : IBinaryNumber<T>
{
    public class UnaryExpr : Expr<T>
    {
        public UnaryExpr(UnaryOperator op, Expr<T> expr) => (Op, Expr) = (op, expr);

        public UnaryOperator Op { get; }
        public Expr<T> Expr { get; }
        public void Deconstruct(out UnaryOperator op, out Expr<T> expr) => (op, expr) = (Op, Expr);
        // 對 Op 進(jìn)行模式匹配
        public override T Eval(params (string Name, T Value)[] args) => Op switch
        {
            // 如果 Op 是 UnaryOperator,則將其解構(gòu)結(jié)果賦值給 op,然后對 op 進(jìn)行匹配,op 是一個枚舉,而 .NET 中的枚舉值都是整數(shù)
            UnaryOperator(var op) => op switch
            {
                // 如果 op 是 Operators.Inv
                Operators.Inv => ~Expr.Eval(args),
                // 如果 op 是 Operators.Min
                Operators.Min => -Expr.Eval(args),
                // 如果 op 是 Operators.LogicalNot
                Operators.LogicalNot => Expr.Eval(args) == T.Zero ? T.One : T.Zero,
                // 如果 op 的值大于 LogicalNot 或者小于 0,表示不是一元運算符
                > Operators.LogicalNot or < 0 => throw new InvalidOperationException($"Expected an unary operator, but got {op}.")
            },
            // 如果 Op 不是 UnaryOperator
            _ => throw new InvalidOperationException("Expected an unary operator.")
        };
    }
}

上面的代碼中,首先利用了 C# 元組可作為左值的特性,分別使用一行代碼就做完了構(gòu)造方法和解構(gòu)方法的賦值:(Op, Expr) = (op, expr)(op, expr) = (Op, Expr)。如果你好奇能否利用這個特性交換多個變量,答案是可以!

Eval 中,首先將類型模式、位置模式和聲明模式組合成 UnaryOperator(var op),表示匹配 UnaryOperator 類型、并且能解構(gòu)出一個元素的東西,如果匹配則將解構(gòu)出來的那個元素賦值給 op。

然后我們接著對解構(gòu)出來的 op 進(jìn)行匹配,這里用到了常數(shù)模式,例如 Operators.Inv 用來匹配 op 是否是 Operators.Inv。常數(shù)模式可以使用各種常數(shù)對對象進(jìn)行匹配。

這里的 > Operators.LogicalNot< 0 則是關(guān)系模式,分別用于匹配大于 Operators.LogicalNot 的值和小于 0 的指。然后利用邏輯模式 or 將兩個模式組合起來表示或的關(guān)系。邏輯模式除了 or 之外還有 andnot。

由于我們在上面窮舉了枚舉中所有的一元運算符,因此也可以將 > Operators.LogicalNot or < 0 換成丟棄模式 _ 或者 var 模式 var foo,兩者都用來匹配任意的東西,只不過前者匹配到后直接丟棄,而后者聲明了個變量 foo 將匹配到的值放到里面:

op switch
{
    // ...
    _ => throw new InvalidOperationException($"Expected an unary operator, but got {op}.")
}

op switch
{
    // ...
    var foo => throw new InvalidOperationException($"Expected an unary operator, but got {foo}.")
}

二元表達(dá)式

二元表達(dá)式用來表示操作數(shù)有兩個的表達(dá)式。有了一元表達(dá)式的編寫經(jīng)驗,二元表達(dá)式如法炮制即可。

public abstract partial class Expr<T> where T : IBinaryNumber<T>
{
    public class BinaryExpr : Expr<T>
    {
        public BinaryExpr(BinaryOperator op, Expr<T> left, Expr<T> right) => (Op, Left, Right) = (op, left, right);

        public BinaryOperator Op { get; }
        public Expr<T> Left { get; }
        public Expr<T> Right { get; }
        public void Deconstruct(out BinaryOperator op, out Expr<T> left, out Expr<T> right) => (op, left, right) = (Op, Left, Right);

        public override T Eval(params (string Name, T Value)[] args) => Op switch
        {
            BinaryOperator(var op) => op switch
            {
                Operators.Add => Left.Eval(args) + Right.Eval(args),
                Operators.Sub => Left.Eval(args) - Right.Eval(args),
                Operators.Mul => Left.Eval(args) * Right.Eval(args),
                Operators.Div => Left.Eval(args) / Right.Eval(args),
                Operators.And => Left.Eval(args) & Right.Eval(args),
                Operators.Or => Left.Eval(args) | Right.Eval(args),
                Operators.Xor => Left.Eval(args) ^ Right.Eval(args),
                Operators.Eq => Left.Eval(args) == Right.Eval(args) ? T.One : T.Zero,
                Operators.Ne => Left.Eval(args) != Right.Eval(args) ? T.One : T.Zero,
                Operators.Gt => Left.Eval(args) > Right.Eval(args) ? T.One : T.Zero,
                Operators.Lt => Left.Eval(args) < Right.Eval(args) ? T.One : T.Zero,
                Operators.Ge => Left.Eval(args) >= Right.Eval(args) ? T.One : T.Zero,
                Operators.Le => Left.Eval(args) <= Right.Eval(args) ? T.One : T.Zero,
                Operators.LogicalAnd => Left.Eval(args) == T.Zero || Right.Eval(args) == T.Zero ? T.Zero : T.One,
                Operators.LogicalOr => Left.Eval(args) == T.Zero && Right.Eval(args) == T.Zero ? T.Zero : T.One,
                < Operators.Add or > Operators.LogicalOr => throw new InvalidOperationException($"Unexpected a binary operator, but got {op}.")
            },
            _ => throw new InvalidOperationException("Unexpected a binary operator.")
        };
    }
}

同理,也可以將 < Operators.Add or > Operators.LogicalOr 換成丟棄模式或者 var 模式。

三元表達(dá)式

三元表達(dá)式包含三個操作數(shù):條件表達(dá)式 Cond、為真的表達(dá)式 Left、為假的表達(dá)式 Right。該表達(dá)式中會根據(jù) Cond 是否為真來選擇取 Left 還是 Right,實現(xiàn)起來較為簡單:

public abstract partial class Expr<T> where T : IBinaryNumber<T>
{
    public class TernaryExpr : Expr<T>
    {
        public TernaryExpr(Expr<T> cond, Expr<T> left, Expr<T> right) => (Cond, Left, Right) = (cond, left, right);

        public Expr<T> Cond { get; }
        public Expr<T> Left { get; }
        public Expr<T> Right { get; }
        public void Deconstruct(out Expr<T> cond, out Expr<T> left, out Expr<T> right) => (cond, left, right) = (Cond, Left, Right);

        public override T Eval(params (string Name, T Value)[] args) => Cond.Eval(args) == T.Zero ? Right.Eval(args) : Left.Eval(args);
    }
}

完成。我們用了僅僅幾十行代碼就完成了全部的核心邏輯!這便是模式匹配的強大之處:簡潔、直觀且高效。

表達(dá)式判等

至此為止,我們已經(jīng)完成了所有的表達(dá)式構(gòu)造、解構(gòu)和計算的實現(xiàn)。接下來我們?yōu)槊恳粋€表達(dá)式實現(xiàn)判等邏輯,即判斷兩個表達(dá)式(字面上)是否相同。

例如 a == b ? 2 : 4a == b ? 2 : 5 不相同,a == b ? 2 : 4c == d ? 2 : 4 不相同,而 a == b ? 2 : 4a == b ? 2 : 4 相同。

為了實現(xiàn)該功能,我們重寫每一個表達(dá)式的 EqualsGetHashCode 方法。

常數(shù)表達(dá)式

常數(shù)表達(dá)式判等只需要判斷常數(shù)值是否相等即可:

public override bool Equals(object? obj) => obj is ConstantExpr(var value) && value == Value;
public override int GetHashCode() => Value.GetHashCode();
參數(shù)表達(dá)式

參數(shù)表達(dá)式判等只需要判斷參數(shù)名是否相等即可:

public override bool Equals(object? obj) => obj is ParameterExpr(var name) && name == Name;
public override int GetHashCode() => Name.GetHashCode();
一元表達(dá)式

一元表達(dá)式判等,需要判斷被比較的表達(dá)式是否是一元表達(dá)式,如果也是的話則判斷運算符和操作數(shù)是否相等:

public override bool Equals(object? obj) => obj is UnaryExpr({ Operator: var op }, var expr) && (op, expr).Equals((Op.Operator, Expr));
public override int GetHashCode() => (Op, Expr).GetHashCode();

上面的代碼中用到了屬性模式 { Operator: var op },用來匹配屬性的值,這里直接組合了聲明模式將屬性 Operator 的值賦值給了 expr。另外,C# 中的元組可以組合起來進(jìn)行判等操作,因此不需要寫 op.Equals(Op.Operator) && expr.Equals(Expr),而是可以直接寫 (op, expr).Equals((Op.Operator, Expr))。

二元表達(dá)式

和一元表達(dá)式差不多,區(qū)別在于這次多了一個操作數(shù):

public override bool Equals(object? obj) => obj is BinaryExpr({ Operator: var op }, var left, var right) && (op, left, right).Equals((Op.Operator, Left, Right));
public override int GetHashCode() => (Op, Left, Right).GetHashCode();
三元表達(dá)式

和二元表達(dá)式差不多,只不過運算符 Op 變成了操作數(shù) Cond

public override bool Equals(object? obj) => obj is TernaryExpr(var cond, var left, var right) && cond.Equals(Cond) && left.Equals(Left) && right.Equals(Right);
public override int GetHashCode() => (Cond, Left, Right).GetHashCode();

到此為止,我們?yōu)樗械谋磉_(dá)式都實現(xiàn)了判等。

一些工具方法

我們重載一些 Expr<T> 的運算符方便我們使用:

public static Expr<T> operator ~(Expr<T> operand) => new UnaryExpr(new(Operators.Inv), operand);
public static Expr<T> operator !(Expr<T> operand) => new UnaryExpr(new(Operators.LogicalNot), operand);
public static Expr<T> operator -(Expr<T> operand) => new UnaryExpr(new(Operators.Min), operand);
public static Expr<T> operator +(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Add), left, right);
public static Expr<T> operator -(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Sub), left, right);
public static Expr<T> operator *(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Mul), left, right);
public static Expr<T> operator /(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Div), left, right);
public static Expr<T> operator &(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.And), left, right);
public static Expr<T> operator |(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Or), left, right);
public static Expr<T> operator ^(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Xor), left, right);
public static Expr<T> operator >(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Gt), left, right);
public static Expr<T> operator <(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Lt), left, right);
public static Expr<T> operator >=(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Ge), left, right);
public static Expr<T> operator <=(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Le), left, right);
public static Expr<T> operator ==(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Eq), left, right);
public static Expr<T> operator !=(Expr<T> left, Expr<T> right) => new BinaryExpr(new(Operators.Ne), left, right);
public static implicit operator Expr<T>(T value) => new ConstantExpr(value);
public static implicit operator Expr<T>(string name) => new ParameterExpr(name);
public static implicit operator Expr<T>(bool value) => new ConstantExpr(value ? T.One : T.Zero);

public override bool Equals(object? obj) => base.Equals(obj);
public override int GetHashCode() => base.GetHashCode();

由于重載了 ==!=,編譯器為了保險起見提示我們重寫 EqualsGetHashCode,這里實際上并不需要重寫,因此直接調(diào)用 base 上的方法保持默認(rèn)行為即可。

然后編寫兩個擴(kuò)展方法用來方便構(gòu)造三元表達(dá)式,和從 Description 中獲取運算符的名字:

public static class Extensions
{
    public static Expr<T> Switch<T>(this Expr<T> cond, Expr<T> left, Expr<T> right) where T : IBinaryNumber<T> => new Expr<T>.TernaryExpr(cond, left, right);
    public static string? GetName<T>(this T op) where T : Enum => typeof(T).GetMember(op.ToString()).FirstOrDefault()?.GetCustomAttribute<DescriptionAttribute>()?.Description;
}

由于有參數(shù)表達(dá)式參與時需要我們提前提供參數(shù)值才能調(diào)用 Eval 進(jìn)行計算,因此我們寫一個交互式的 Eval 來在計算過程中遇到參數(shù)表達(dá)式時提示用戶輸入值,起名叫做 InteractiveEval

public T InteractiveEval()
{
    var names = Array.Empty<string>();
    return Eval(GetArgs(this, ref names, ref names));
}
private static T GetArg(string name, ref string[] names)
{
    Console.Write($"Parameter {name}: ");
    string? str;
    do { str = Console.ReadLine(); }
    while (str is null);
    names = names.Append(name).ToArray();
    return T.Parse(str, NumberStyles.Number, null);
}
private static (string Name, T Value)[] GetArgs(Expr<T> expr, ref string[] assigned, ref string[] filter) => expr switch
{
    TernaryExpr(var cond, var left, var right) => GetArgs(cond, ref assigned, ref assigned).Concat(GetArgs(left, ref assigned,ref assigned)).Concat(GetArgs(right, ref assigned, ref assigned)).ToArray(),
    BinaryExpr(_, var left, var right) => GetArgs(left, ref assigned, ref assigned).Concat(GetArgs(right, ref assigned, refassigned)).ToArray(),
    UnaryExpr(_, var uexpr) => GetArgs(uexpr, ref assigned, ref assigned),
    ParameterExpr(var name) => filter switch
    {
        [var head, ..] when head == name => Array.Empty<(string Name, T Value)>(),
        [_, .. var tail] => GetArgs(expr, ref assigned, ref tail),
        [] => new[] { (name, GetArg(name, ref assigned)) }
    },
    _ => Array.Empty<(string Name, T Value)>()
};

這里在 GetArgs 方法中,模式 [var head, ..] 后面跟了一個 when head == name,這里的 when 用來給模式匹配指定額外的條件,僅當(dāng)條件滿足時才匹配成功,因此 [var head, ..] when head == name 的含義是,匹配至少含有一個元素的列表,并且將頭元素賦值給 head,且僅當(dāng) head == name 時匹配才算成功。

最后我們再重寫 ToString 方法方便輸出表達(dá)式,就全部大功告成了。

測試

接下來讓我測試測試我們編寫的表達(dá)式計算器:

Expr<int> a = 4;
Expr<int> b = -3;
Expr<int> x = "x";
Expr<int> c = !((a + b) * (a - b) > x);
Expr<int> y = "y";
Expr<int> z = "z";
Expr<int> expr = (c.Switch(y, z) - a > x).Switch(z + a, y / b);
Console.WriteLine(expr);
Console.WriteLine(expr.InteractiveEval());

運行后得到輸出:

((((! ((((4) + (-3)) * ((4) - (-3))) > (x))) ? (y) : (z)) - (4)) > (x)) ? ((z) + (4)) : ((y) / (-3))

然后我們給 x、yz 分別設(shè)置成 42、27 和 35,即可得到運算結(jié)果:

Parameter x: 42
Parameter y: 27
Parameter z: 35
-9

再測測表達(dá)式判等邏輯:

Expr<int> expr1, expr2, expr3;
{
    Expr<int> a = 4;
    Expr<int> b = -3;
    Expr<int> x = "x";
    Expr<int> c = !((a + b) * (a - b) > x);
    Expr<int> y = "y";
    Expr<int> z = "z";
    expr1 = (c.Switch(y, z) - a > x).Switch(z + a, y / b);
}

{
    Expr<int> a = 4;
    Expr<int> b = -3;
    Expr<int> x = "x";
    Expr<int> c = !((a + b) * (a - b) > x);
    Expr<int> y = "y";
    Expr<int> z = "z";
    expr2 = (c.Switch(y, z) - a > x).Switch(z + a, y / b);
}

{
    Expr<int> a = 4;
    Expr<int> b = -3;
    Expr<int> x = "x";
    Expr<int> c = !((a + b) * (a - b) > x);
    Expr<int> y = "y";
    Expr<int> w = "w";
    expr3 = (c.Switch(y, w) - a > x).Switch(w + a, y / b);
}

Console.WriteLine(expr1.Equals(expr2));
Console.WriteLine(expr1.Equals(expr3));

得到輸出:

True
False

活動模式

在未來,C# 將會引入活動模式,該模式允許用戶自定義模式匹配的方法,例如:

static bool Even<T>(this T value) where T : IBinaryInteger<T> => value % 2 == 0;

上述代碼定義了一個 T 的擴(kuò)展方法 Even,用來匹配 value 是否為偶數(shù),于是我們便可以這么使用:

var x = 3;
var y = x switch
{
    Even() => "even",
    _ => "odd"
};

此外,該模式還可以和解構(gòu)模式結(jié)合,允許用戶自定義解構(gòu)行為,例如:

static bool Int(this string value, out int result) => int.TryParse(value, out result);

然后使用的時候:

var x = "3";
var y = x switch
{
    Int(var result) => result,
    _ => 0
};

即可對 x 這個字符串進(jìn)行匹配,如果 x 可以被解析為 int,就取解析結(jié)果 result,否則取 0。

到此,關(guān)于“C#模式匹配有哪些及怎么實現(xiàn)”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI