简体   繁体   English

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

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

I'm looking at C# 7's new switch statement, and while it's awesome that I can switch on the type as part of pattern matching, I wonder if I can avoid re-stating the type in case I already know it? 我正在看C#7的新switch语句,虽然我可以打开类型作为模式匹配的一部分很棒,但我想知道如果我已经知道它可以避免重新说明类型吗?

Example: 例:

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

Here, my case statement re-states string x even though the type I'm switching on is already a string, and I only care about it's Length and if it int.TryParse s. 在这里,我的case语句重新声明string x即使我正在打开的类型已经是一个字符串,我只关心它的Length ,如果它是int.TryParse s。

Just omitting it doesn't compile: 省略它不会编译:

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

So I'm just wondering if there is a way to omit it, or if it's just part of the pattern matching syntax that I have to accept. 所以我只是想知道是否有一种方法可以省略它,或者它只是我必须接受的模式匹配语法的一部分。

You could use var pattern: 你可以使用var pattern:

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

Or even better, var pattern with a discard: 甚至更好, var disc with discard:

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

No, you can't omit the type (or var keyword masking the type), as it is a part of pattern matching here. 不,你不能省略类型(或var关键字掩盖类型),因为它是模式匹配的一部分。

Consider class hierarchy (this will not compile in C#7 , but will compile in further versions after full implementation) 考虑类层次结构(这不会在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;

Now we get a variable like this: 现在我们得到一个这样的变量:

Geometry g = new Square(5);

Now we do the switch over it: 现在我们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;
}

Back to your case, consider the code: 回到你的情况,考虑代码:

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

So type checking is a part of pattern matching and you can't omit it (and for C#7 it's only available to switch on types, full support is planned for C#8 ). 所以类型检查是模式匹配的一部分,你不能省略它(对于C#7它只能用于打开类型,计划为C#8全面支持)。 Example was brought from here . 示例来自这里 The previous step was the when clause for exception handling in C#6 上一步是C#6异常处理when子句

I've used the following. 我使用了以下内容。 Aesthetically it is displeasing, but it does have two advantages. 在美学上它令人不快,但它确实有两个优点。 It's fairly easy to understand and it compiles. 它很容易理解并且编译。 The x ends up not being used. x最终没有被使用。 The variable in the switch statement can be a dummy. switch语句中的变量可以是虚拟的。 If you have particularly complicated heavily nested if-then code this method can be used and can be easier to /read/understand. 如果您有特别复杂的嵌套if-then代码,则可以使用此方法,并且可以更容易/读取/理解。 Anyone know a better way? 谁知道更好的方法?

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM