C# 6 元组应用 Part 2:C# 也玩模式匹配

C# 7给我们带来了一个半吊子的 switch 语句模式匹配,只能简单的匹配类型而已,完全没有什么用处。这里我提供个更好的简单实现,用 C# 6 的 ValueTuple 模拟函数式语言的模式匹配功能。

首先就是实现:

 1   public static class ValueTupleExtensions
 2     {
 3 
 4         /// <summary>
 5         /// 至少匹配一个条件
 6         /// </summary>
 7         /// <typeparam name="T"></typeparam>
 8         /// <param name=""></param>
 9         /// <returns></returns>
10         public static TResult MatchOne<TResult>(params (Func<bool> condExpr, Func<TResult> resultExpr)[] pairs)
11         {
12             foreach (var pair in pairs)
13             {
14                 if (pair.condExpr())
15                 {
16                     return pair.resultExpr();
17                 }
18             }
19             throw new InvalidOperationException("无匹配的表达式");
20         }
21 
22         /// <summary>
23         /// 匹配默认或指定的条件
24         /// </summary>
25         /// <typeparam name="TResult"></typeparam>
26         /// <param name="defaultMatch"></param>
27         /// <param name="matchs"></param>
28         /// <returns></returns>
29         public static TResult MatchOneOrDefault<TResult>(
30             Func<TResult> defaultMatchExpr,
31             params (Func<bool> condExpr, Func<TResult> resultExpr)[] matchs)
32         {
33             foreach (var pair in matchs)
34             {
35                 if (pair.condExpr())
36                 {
37                     return pair.resultExpr();
38                 }
39             }
40 
41             return defaultMatchExpr();
42         }
43 
44         public static TOutput MatchOne<TInput, TOutput>(TInput inputValue, params (TInput matcheValue, Func<TOutput> resultValueExpr)[] pairs)
45             where TInput : IEquatable<TInput>
46         {
47             foreach (var pair in pairs)
48             {
49                 if (inputValue.Equals(pair.matcheValue))
50                 {
51                     return pair.resultValueExpr();
52                 }
53             }
54 
55             throw new InvalidOperationException("无匹配的值");
56         }
57 
58         public static TOutput MatchOneOrDefault<TInput, TOutput>(TInput inputValue, params (TInput matcheValue, Func<TOutput> resultValueExpr)[] pairs)
59             where TInput : IEquatable<TInput>
60         {
61             if (inputValue == null)
62             {
63                 throw new ArgumentNullException(nameof(inputValue));
64             }
65 
66             foreach (var pair in pairs)
67             {
68                 if (pair.matcheValue == null)
69                 {
70                     throw new ArgumentNullException(nameof(pairs));
71                 }
72 
73                 if (inputValue.Equals(pair.matcheValue))
74                 {
75                     return pair.resultValueExpr();
76                 }
77             }
78             return default(TOutput);
79         }
80     }

然后用起来就非常简单了,首先使用 `using static` 引入静态函数:

using static ValueTupleExtensions;

然后我们实际操练下:

 class Program
    {
        static void Main(string[] args)
        {
            var a = 5;

            //最简单的重载,与某个值相等就执行后面的 lambda 表达式
            var matched = MatchOne(
                a,
                (1, () => "111"),
                (5, () => "555")
            );

            Console.WriteLine($"matched={matched}");

            //更自由的形式,第一个 lambda 相当于 if
            matched = MatchOne(
                (() => a == 1, () => "111"),
                (() => a == 5, () => "555")
            );

            Console.WriteLine($"matched={matched}");


            Console.ReadKey();
        }
    }

虽然括号略多,不过还是很好玩的吧。

Have fun!

posted on 2017-06-26 17:28  李屠户  阅读(365)  评论(0编辑  收藏  举报