【问题标题】:What are the restrictions of the pattern matching mechanics?模式匹配机制的限制是什么?
【发布时间】:2017-02-03 05:54:40
【问题描述】:

就我个人而言,我只知道动态不能用于模式匹配,这被认为是一个遗憾:(

dynamic foo = 10;
switch(foo) {
    case int i:
    break;
}

另外,值元组/新元组不能用于模式匹配:

dynamic foo = (420, 360);
switch(foo) {
    case (int, int) i:
    break;
}

在当前版本的 C#7 中已将其删除,并分配给将来使用。

还有哪些我不能做的事情?

【问题讨论】:

  • 投票重新开放,因为限制记录在 Roslyn 问题中,愿意花时间这样做的人可以在此处准确总结。
  • @DavidArno - 当然,如果您想将其限制为实际提出的想法。但是当它只是问“我不能做的其他事情是什么?”时,这肯定是一个无限的列表吗?
  • @Damien_The_Unbeliever,那么为什么不通过重组问题来帮助 OP,使其不需要无限列表答案?

标签: c# c#-7.0


【解决方案1】:

C# 7 中的新模式匹配功能包括以下内容:

  • 支持类型切换,
  • var 模式的简单使用,
  • 在 case 语句中添加了 when 保护,
  • x is T y 模式表达式。

您的示例侧重于其中的第一个。而类型切换很可能是这些新功能中最受欢迎和最常用的。虽然存在一些限制,例如您提到的那些限制,但可以使用其他功能来解决其中的许多限制。

例如,您的第一个限制可以通过将foo 装箱object 轻松解决:

dynamic foo = 10;
switch ((object)foo)
{
    case int i:
        Console.WriteLine("int");
        break;
    default:
        Console.WriteLine("other");
        break;
}

将按预期打印int

var 模式和守卫可用于解决您的第二个限制:

dynamic foo = (420, 360);
switch (foo)
{
    case var ii when ii.GetType() == typeof((int, int)):
        Console.WriteLine("(int,int)");
        break;
    default:
        Console.WriteLine("other");
        break;
}

将打印(int,int)

另外,值元组可以用于类型切换,你只需要使用长手语法:

var foo = (420, 360);
switch (foo)
{
    case ValueTuple<int,int> x:
        Console.WriteLine($"({x.Item1},{x.Item2})");
        break;
    default:
        Console.WriteLine("other");
        break;
}

上面将打印(420,360)

就我个人而言,C# 7 中模式匹配的最大限制是缺少使用match 关键字的模式匹配表达式。最初,此版本计划使用以下内容,但为 pulled due to time constraints

var x = 1;
var y = x match (
    case int _ : "int",
    case * : "other"
);

这可以使用switch 来解决,但是很麻烦:

var x = 1;
var y = IntOrOther(x);

...

private string IntOrOther(int i)
{
    switch (i)
    {
        case int _ : return "int";
        default: return "other";
    }
}

但是这里有许多 3rd 方模式匹配库的帮助,比如我自己的 Succinc<T> library,让我们把它写成:

var x = 1;
var y = x.TypeMatch().To<string>()
         .Caseof<int>().Do("int")
         .Else("other")
         .Result();

它不如 match 关键字好,但它是一种可选的解决方法,直到该功能出现在以后的语言版本中。

要真正了解 C# 7 施加的限制,值得参考pattern matching spec on GitHub 并将其与 C# 的下一个版本中的内容进行比较。但仔细观察,很明显所有这些都有变通方法。

这个问题最初是封闭的,因为它按照目前的措辞是开放式的。举几个愚蠢的例子,C# 7 模式匹配的限制是它不会让你喝上一杯完美的咖啡,或者让你在几秒钟内飞过世界……但我更愿意回答这个问题的精神。答案真的是,唯一的限制是你的想象力。如果您不让它限制您,那么必须考虑到变通方法具有可读性和/或性能影响这一事实。它们可能是现实世界中唯一的限制。

【讨论】:

  • 您可以通过将开关放入 lambda gist.github.com/bradphelan/350da3554ca8db3f0fa90ee598dabe58 来伪造匹配表达式
  • @bradgonesurfing,如果您愿意,请随时编辑我的答案以包含该内容,而不仅仅是将其作为评论。
  • 您可以使用var y = x is int _ ? "int" : "other"; 而不是match 作为解决方法。由于您可以链接三元运算符,因此即使在更复杂的情况下也会有所帮助。
猜你喜欢
  • 1970-01-01
  • 2015-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-14
  • 2019-09-03
  • 1970-01-01
相关资源
最近更新 更多