C#关键字

C#关键字-switch的使用


而本篇文章只是针对 switch (C# 参考) 文章做个笔记而已,避免自己忘记。

一些 switch 语法上要注意的项目如下

一、switch 比对运算式的语法

switch 比对运算式提供与 case 标签中的模式进行比对的值。 它的语法为:

switch (比对运算式)
{
}

如下范例

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int caseSwitch = 1;

            switch (caseSwitch)
            {
                case 1:
                    Console.WriteLine("Case 1");
                    break;
                case 2:
                    Console.WriteLine("Case 2");
                    break;
                default:
                    Console.WriteLine("Default case");
                    break;
            }
            Console.ReadKey();
        }
    }
}

说明:

1、如果比对运算式不符合任何其他 case 标签,则会跳到 default case (黄色框框)。 如果 default case 不存在,而且比对运算式不符合任何其他 case 标签,则程序流程会离开 switch 陈述式。

2、default case 可以依任何顺序出现在 switch 陈述式中。 不论它在原始程序中的顺序为何,一律都会在评估过所有 case 标签之后最后才进行评估。

3、在 C# 6 中,比对运算式必须是返回下列类型之值的运算式︰char、string、bool、整数值、enum 值

4、从 C# 7 开始,比对运算式可以是任何非 Null 运算式。

二、参数区段

一个参数区段可以使用 break、goto case、throw 或 return 陈述式明确地指出来。

普遍地switch 陈述式包含一个或多个参数区段,每一个参数区段都会由关键字“break”结尾。

每个参数区段都包含一或多个“case 标签”(普遍情况是一个),后面接着一或多个陈述式。

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int caseSwitch = 2;

            switch (caseSwitch)
            {
                case 1:
                    Console.WriteLine("Case 1");
                    break;
                case 2:
                case 3:
                    Console.WriteLine($"Case {caseSwitch}");
                    break;
                default:
                    Console.WriteLine($"An unexpected value ({caseSwitch})");
                    break;
            }

            Console.ReadKey();
        }
    }
}

虽然每个参数区段可包含一或多个“case 标签”;但考虑多个“case 标签”情形时,

而每一个“case 标签”又至少会有一个陈述式时,

则每一个“case 标签”必须再用关键字“break”隔出一个参数区段,否则会出错,如下范例。

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int caseSwitch = 2;

            switch (caseSwitch)
            {
                case 1:
                    Console.WriteLine("Case 1");
                    break;
                case 2:
                    Console.WriteLine("Case 2");
                    //break;
                case 3:
                    Console.WriteLine("Case 3");
                    break;
                default:
                    Console.WriteLine($"An unexpected value ({caseSwitch})");
                    break;
            }

            Console.ReadKey();
        }
    }
}

另外,也不可以有两个 case 标签包含相同的运算式,如下范例是错误的。

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int caseSwitch = 2;

            switch (caseSwitch)
            {
                case 1:
                    Console.WriteLine("Case 1");
                    break;
                case 2:
                case 2:
                    Console.WriteLine($"Case {caseSwitch}");
                    break;
                default:
                    Console.WriteLine($"An unexpected value ({caseSwitch})");
                    break;
            }

            Console.ReadKey();
        }
    }
}

一个例外状况也是有效的,因为它可确保程控权无法切换到 default 参数区段,如下范例。

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int caseSwitch = 2;

            switch (caseSwitch)
            {
                case 1:
                    Console.WriteLine("Case 1...");
                    break;
                case 2:
                case 3:
                    Console.WriteLine("... and/or Case 2");
                    break;
                case 4:
                    while (true)
                        Console.WriteLine("Endless looping. . . .");
                default:
                    Console.WriteLine("Default value...");
                    break;
            }

            Console.ReadKey();
        }
    }
}

三、C# 7 case 标签

从 C#1 到 C# 6 只支持常数模式,且不允许重复常数值,所以 case 标签定义互斥值,而且只有一个模式可以符合比对运算式。 因此,case 陈述式的出现顺序并不重要。

不过,在 C# 7 中,因为支持其他模式(请参阅C# 7.0 新功能的pattern matching),所以 case 标签不需要定义互斥值,而且可以有多个模式符合比对运算式。 因为只会执行包含第一个相符模式的参数区段中的陈述式,所以 case 陈述式的出现顺序现在十分重要。

如果 C# 侦测到一或多个 case 陈述式等于或为先前陈述式子集的参数区段,则会产生编译器错误 CS8120:“The switch case has already been handled by a previous case.”,如下范例

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int switch_on = 2;

            switch (switch_on)
            {
                case int a:
                    Console.WriteLine($"case int {a}");
                    break;
                case 1:
                    Console.WriteLine("case 1");
                    break;
            }
            Console.ReadKey();
        }
    }
}

由于程序是依序比对,而“case int a”条件早已包含“case 1 ”,

所以编译器将会很聪明地发现错误CS8120:“The switch case has already been handled by a previous case.”

这时调整 case 的顺序可以解决错误,或是使用关键字“when”来排除特例,如下范例

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            int switch_on = 1;

            switch (switch_on)
            {
                case int a when a != 1:
                    Console.WriteLine($"case int {a}");
                    break;
                case 1:
                    Console.WriteLine("case 1");
                    break;
            }
            Console.ReadKey();
        }
    }
}

参考数据:

switch (C# 参考)