是否有一种方法可以通过多个case语句而不声明case值:重复?

我知道这很管用:

switch (value)
{
   case 1:
   case 2:
   case 3:
      // Do some stuff
      break;
   case 4:
   case 5:
   case 6:
      // Do some different stuff
      break;
   default:
       // Default stuff
      break;
}

但我想这样做:

switch (value)
{
   case 1,2,3:
      // Do something
      break;
   case 4,5,6:
      // Do something
      break;
   default:
      // Do the Default
      break;
}

这是我从另一种语言中想到的语法,还是我遗漏了什么?


当前回答

.NET Framework 3.5有如下的范围:

可列举的。范围从MSDN

你可以将它与“contains”和IF语句一起使用,因为有人说SWITCH语句使用“==”操作符。

这里有一个例子:

int c = 2;
if(Enumerable.Range(0,10).Contains(c))
    DoThing();
else if(Enumerable.Range(11,20).Contains(c))
    DoAnotherThing();

但是我认为我们可以有更多的乐趣:因为您不需要返回值,而且这个操作不接受参数,所以您可以轻松地使用操作!

public static void MySwitchWithEnumerable(int switchcase, int startNumber, int endNumber, Action action)
{
    if(Enumerable.Range(startNumber, endNumber).Contains(switchcase))
        action();
}

这个新方法的旧示例:

MySwitchWithEnumerable(c, 0, 10, DoThing);
MySwitchWithEnumerable(c, 10, 20, DoAnotherThing);

因为你传递的是动作,而不是值,所以你应该省略圆括号,这很重要。如果需要带参数的函数,只需将Action的类型更改为Action<ParameterType>。如果需要返回值,请使用Func<ParameterType, ReturnType>。

在c# 3.0中,没有简单的局部应用程序来封装case参数相同的事实,但您可以创建一个小的辅助方法(虽然有点啰嗦)。

public static void MySwitchWithEnumerable(int startNumber, int endNumber, Action action){ 
    MySwitchWithEnumerable(3, startNumber, endNumber, action); 
}

这里有一个例子,说明新的函数导入语句如何比旧的命令式语句更强大和优雅。

其他回答

我想这个问题已经有答案了。然而,我认为你仍然可以通过以下方式在语法上更好地混合这两个选项:

switch (value)
{
    case 1: case 2: case 3:          
        // Do Something
        break;
    case 4: case 5: case 6: 
        // Do Something
        break;
    default:
        // Do Something
        break;
}

c#中switch的一个不太为人所知的方面是它依赖于操作符=,因为它可以被覆盖,所以你可以有这样的东西:


string s = foo();

switch (s) {
  case "abc": /*...*/ break;
  case "def": /*...*/ break;
}

c# 7的原始答案

在c# 7中(默认在Visual Studio 2017中可用)。NET Framework 4.6.2),基于范围的切换现在可以通过switch语句实现,这将有助于解决OP的问题。

例子:

int i = 5;

switch (i)
{
    case int n when (n >= 7):
        Console.WriteLine($"I am 7 or above: {n}");
        break;

    case int n when (n >= 4 && n <= 6 ):
        Console.WriteLine($"I am between 4 and 6: {n}");
        break;

    case int n when (n <= 3):
        Console.WriteLine($"I am 3 or less: {n}");
        break;
}

// Output: I am between 4 and 6: 5

注:

括号(和)在when条件中不是必需的,但在本例中用于突出显示比较。 Var也可以用来代替int。例如:case var n when n >= 7:。


c# 9的更新示例

switch(myValue)
{
    case <= 0:
        Console.WriteLine("Less than or equal to 0");
        break;
    case > 0 and <= 10:
        Console.WriteLine("More than 0 but less than or equal to 10");
        break;
    default:
        Console.WriteLine("More than 10");
        break;
}

or

var message = myValue switch
{
    <= 0 => "Less than or equal to 0",
    > 0 and <= 10 => "More than 0 but less than or equal to 10",
    _ => "More than 10"
};
Console.WriteLine(message);

在c# 9中出现了关系模式匹配。这允许我们这样做:

switch (value)
{
    case 1 or 2 or 3:
      // Do stuff
      break;
    case 4 or 5 or 6:
      // Do stuff
      break;
    default:
        // Do stuff
        break;
}

在c# 9的关系模式深度教程中

c# 9.0的模式匹配更改

关系模式允许程序员表达输入 值与常量比较时必须满足关系约束 价值

只是为了增加对话,使用. net 4.6.2我还能够做以下工作。 我测试了代码,它确实为我工作。

你也可以做多个“或”语句,如下所示:

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when b.Contains("text3") || b.Contains("text4") || b.Contains("text5"):
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }

你也可以检查它是否与数组中的值匹配:

            string[] statuses = { "text3", "text4", "text5"};

            switch (value)
            {
                case string a when a.Contains("text1"):
                    // Do Something
                    break;
                case string b when statuses.Contains(value):                        
                    // Do Something else
                    break;
                default:
                    // Or do this by default
                    break;
            }