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

Can I simplify this C# 7 switch statement to not re-state the type?

我正在查看 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;
    }
}

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

只是省略它不会编译:

//  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):

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

您可以使用 var 模式:

case var x when x.Length == 3 && int.TryParse(x, out int i):

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

case var _ when s.Length == 3 && int.TryParse(s, out int i):

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

考虑 class 层次结构(这不会在 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;

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

Geometry g = new Square(5);

现在我们对其进行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;
}

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

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;
}

所以类型检查是模式匹配的一部分,你不能省略它(对于C#7它只能用于打开类型,完全支持是计划 C#8)。示例来自 here. The previous step was the when clause for exception handling in C#6

我使用了以下内容。从美学上讲,它令人不快,但它确实有两个优点。它很容易理解并且可以编译。 x 最终未被使用。 switch 语句中的变量可以是虚拟变量。如果你有特别复杂的大量嵌套的 if-then 代码,可以使用这个方法并且可以更容易 /read/understand。有人知道更好的方法吗?

switch (dummyString)
{
    case string x1 when word = "entry": 
        DoEntry(); 
        break;

    case string x2 when word = "exit" && door="front":
        DoFrontDoorExit();
        break;

    case string x3 when word = "exit" && door="rear":
        DoRearDoorExit();
        break;

    case string x4 when Tomorrow() == "Tuesday":
        BuyALotteryTicket()
        break;

    default: 
        break; 
}