我可以简化这个C#7 switch语句以不重新声明类型吗?

Mic*_*tum 8 c# pattern-matching c#-7.0

我正在看C#7的新switch语句,虽然我可以打开类型作为模式匹配的一部分很棒,但我想知道如果我已经知道它可以避免重新说明类型吗?

例:

private static void BetterSwitchCase(string s)
{
    switch (s)
    {
        case string x when x.Length == 3 && int.TryParse(x, out int i):
            Console.WriteLine($"s is a string that parses to {i}");
            break;
        default:
            Console.WriteLine("No Match.");
            break;
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我的case语句重新声明,string x即使我正在打开的类型已经是一个字符串,我只关心它Length,如果它int.TryParse是.

省略它不会编译:

//  Syntax error, ':' expected
case when s.Length == 3 && int.TryParse(s, out int i):

// A constant value is expected
case s when s.Length == 3 && int.TryParse(s, out int i):
Run Code Online (Sandbox Code Playgroud)

所以我只是想知道是否有一种方法可以省略它,或者它只是我必须接受的模式匹配语法的一部分.

svi*_*ick 8

你可以使用var模式:

case var x when x.Length == 3 && int.TryParse(x, out int i):
Run Code Online (Sandbox Code Playgroud)

或者甚至更好,var丢弃的模式:

case var _ when s.Length == 3 && int.TryParse(s, out int i):
Run Code Online (Sandbox Code Playgroud)


VMA*_*Atm 3

不,您不能省略类型(或var屏蔽类型的关键字),因为它是此处模式匹配的一部分。

考虑类层次结构(这不会在 中编译C#7,但会在完全实现后在进一步的版本中编译)

class Geometry();
class Triangle(int Width, int Height, int Base) : Geometry;
class Rectangle(int Width, int Height)          : Geometry;
class Square(int width)                         : Geometry;
Run Code Online (Sandbox Code Playgroud)

现在我们得到一个像这样的变量:

Geometry g = new Square(5);
Run Code Online (Sandbox Code Playgroud)

现在我们switch重新做一下:

using static System.Console;

switch (g)
{
    // check that g is a Triangle and deconstruct it into local variables
    case Triangle(int Width, int Height, int Base):
        WriteLine($"{Width} {Height} {Base}");
        break;

    // same for Rectangle
    case Rectangle(int Width, int Height):
        WriteLine($"{Width} {Height}");
        break;

    // same for Square
    case Square(int Width):
        WriteLine($"{Width}");
        break;

    // no luck
    default:
        WriteLine("<other>");
        break;
}
Run Code Online (Sandbox Code Playgroud)

回到你的案例,考虑代码:

switch (s)
{
    case string x when x.Length == 3 && int.TryParse(x, out int i):
        Console.WriteLine($"s is a string that parses to {i}");
        break;
    // will not compile with error
    // An expression of type string cannot be handled by a pattern of type int.
    case int x:
        break;

    // will win pattern matching and print the line
    // {s} is an object
    case object x:
        Console.WriteLine($"{s} is an object");

    default:
        Console.WriteLine("No Match.");
        break;
}
Run Code Online (Sandbox Code Playgroud)

因此类型检查是模式匹配的一部分,您不能省略它(并且由于C#7它只能用于打开类型,因此计划提供全面支持C#8)。示例是从这里带来的。上一步是异常处理的when子句C#6