C# 当对子句求值时,switch语句的顺序是什么?

C# 当对子句求值时,switch语句的顺序是什么?,c#,switch-statement,pattern-matching,C#,Switch Statement,Pattern Matching,考虑以下示例: public static double ComputeArea_Version3(object shape) { switch (shape) { case Square s when s.Side == 0: case Circle c when c.Radius == 0: return 0; case Square s: return s.Side * s.S

考虑以下示例:

public static double ComputeArea_Version3(object shape)
{
    switch (shape)
    {
        case Square s when s.Side == 0:
        case Circle c when c.Radius == 0:
            return 0;

        case Square s:
            return s.Side * s.Side;
        case Circle c:
            return c.Radius * c.Radius * Math.PI;
        default:
            throw new ArgumentException(
                message: "shape is not a recognized shape",
                paramName: nameof(shape));
    }
}
当s.Side==0时,
when
子句
case Square s:
是否保证在更通用的
case Square s:
之前执行?是什么决定了
开关中的顺序和位置?如果我写的是:

public static double ComputeArea_Version3(object shape)
{
    switch (shape)
    {
        case Square s:
            return s.Side * s.Side;
        case Circle c:
            return c.Radius * c.Radius * Math.PI;

        case Square s when s.Side == 0:
        case Circle c when c.Radius == 0:
            return 0;

        default:
            throw new ArgumentException(
                message: "shape is not a recognized shape",
                paramName: nameof(shape));
    }
}

条款永远不会被评估时,
条款会不会被评估?

案例条款会按照代码指示的顺序被评估

一个开关不过是一系列的if-then-if-then-else等等,在一个简洁易读的问题上

因此,如果您放置一个break、return、throw或goto语句,那么它会在第一个true条件下中断解析,否则它们也会被连续检查

例如,您可以编写:

case 0:
case 1:
  DoSomething();
  break;
但你不能写:

case 0:
  DoSomething();
  // break or return or throw or goto needed here
case 1:
  DoAnotherSomething();
  break;
您可以使用一些示例逐行调试以检查这一点

您的第二个示例无法编译,因为必须将条件从特定设置为一般设置

例如:

object instance = new Form();
switch ( instance )
{
  case Form f when f.Text == "Test":
    return;
  case Form f:
    return;
  case Label l:
    return;
}
生成的IL代码:

// object obj = new Form();
IL_0001: newobj instance void [System.Windows.Forms]System.Windows.Forms.Form::.ctor()
IL_0006: stloc.0
// object obj2 = obj;
IL_0007: ldloc.0
IL_0008: stloc.s 7
// object obj3 = obj2;
IL_000a: ldloc.s 7
IL_000c: stloc.1
// if (obj3 == null)
IL_000d: ldloc.1
// (no C# code)
IL_000e: brtrue.s IL_0012

// }
IL_0010: br.s IL_002c

// if ((form = (obj3 as Form)) == null)
IL_0012: ldloc.1
IL_0013: isinst [System.Windows.Forms]System.Windows.Forms.Form
// (no C# code)
IL_0018: dup
IL_0019: stloc.2
IL_001a: brfalse.s IL_0020

IL_001c: br.s IL_002e

IL_001e: br.s IL_0048

// if ((label = (obj3 as Label)) != null)
IL_0020: ldloc.1
IL_0021: isinst [System.Windows.Forms]System.Windows.Forms.Label
// (no C# code)
IL_0026: dup
IL_0027: stloc.3
IL_0028: brfalse.s IL_002c

IL_002a: br.s IL_004f

IL_002c: br.s IL_0056

// Form form2 = form;
IL_002e: ldloc.2
IL_002f: stloc.s 4
// if (!(form2.Text == "Test"))
IL_0031: ldloc.s 4
IL_0033: callvirt instance string [System.Windows.Forms]System.Windows.Forms.Control::get_Text()
IL_0038: ldstr "Test"
IL_003d: call bool [mscorlib]System.String::op_Equality(string, string)
// (no C# code)
IL_0042: brtrue.s IL_0046

IL_0044: br.s IL_001e

IL_0046: br.s IL_0056

// Form form3 = form;
IL_0048: ldloc.2
IL_0049: stloc.s 5
// (no C# code)
IL_004b: br.s IL_004d

IL_004d: br.s IL_0056

// Label label2 = label;
IL_004f: ldloc.3
IL_0050: stloc.s 6
// (no C# code)
IL_0052: br.s IL_0054

IL_0054: br.s IL_0056

IL_0056: ret
如您所见,此代码是一系列测试和分支

确认订单与代码中所写的一致:

开关表达式按文本顺序计算。执行 传输到与交换机匹配的第一个交换机标签 表情

虽然您的第二个示例不会像@OlivierRogier在中解释的那样编译是正确的,但顺序仍然很重要。考虑这个代码片段:

object o = 42;

switch (o)
{
   case int i when i > 10:
       Console.WriteLine("Greater 10");
       break;
   case int j when j > 20:
       Console.WriteLine("Greater 20");
       break;
}
这将打印大于10的
。但是如果你把这两个案例切换到

switch (o)
{
   case int j when j > 20:
       Console.WriteLine("Greater 20");
       break;
   case int i when i > 10:
       Console.WriteLine("Greater 10");
       break;
}

它仍然会编译,但会打印
Greater 20

您已经在调用
return
行,因此它不会到达后续的case语句。我想他是在问,当不满足case时,它们是否会按顺序进行。他想知道这些条件是否按顺序评估。答案是肯定的,这些案例是按照它们提供的顺序考虑的。@DetectivePikachu你是对的。我不认为你的答案大体上是正确的。据我所知,C#能够为常量值
switch
语句生成哈希表,这将使排序静音。它只会为>7种情况生成字典。尽管我不知道编译器会产生一个错误,但排序仍然是无意义的。
在第二个示例中,开关案例已经由前一个案例处理。
。好的观点。解释这个编译错误何时出现很重要:“开关案例已经被前一个案例处理过。”有趣的事实是,当
时,你可以重复相同的
案例,编译器不会在意,因为它只会检查当
时是否有一个
案例
已经覆盖了
案例,但是当
零件时,不会真正检查