模式匹配机制有哪些限制?

时间:2017-02-03 05:54:40

标签: c# c#-7.0

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

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

此外,有价值的元组/新元组不能用于模式匹配:

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

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

我不能做的其他事情是什么?

1 个答案:

答案 0 :(得分:7)

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

  • 支持类型切换,
  • 简单使用var模式,
  • 在案件陈述中添加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";
    }
}

但是这里有许多第三方模式匹配库,例如我自己的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的模式匹配是它不会让你成为一杯完美的咖啡,或者在几秒钟内将你带到世界各地......但我更愿意回答这个问题的精神。答案真的是唯一的限制是你的想象力。如果你不允许这限制你,那么必须考虑到解决方案具有可读性和/或性能影响这一事实。它们可能是唯一的现实世界限制。