C#中的Switch case语句 - 需要一个常量值

121

我的代码如下:

public static void Output<T>(IEnumerable<T> dataSource) where T : class
{   
    dataSourceName = (typeof(T).Name);
    switch (dataSourceName)
    {
        case (string)typeof(CustomerDetails).Name.ToString(); :
            var t = 123;
            break;
        default:
            Console.WriteLine("Test");
    }
}

但是这并没有起作用。case语句给我一个错误,说需要一个常量变量。请帮我解决,谢谢!

9个回答

79

我有一个技巧(不要问我细节——我无法提供,但它对我很有效):

switch (variable_1)
{
    case var value when value == variable_2: // that's the trick
        DoSomething();
        break;
    default:
        DoSomethingElse();
        break;
}

2
哎呀,谢谢!!!这为什么会起作用?!?! 它也可以与_C# 8.0变量开关lambda_一起使用:variable_1 switch var value when value == variable_2: - Marcelo Scofano Diniz
1
在我的代码中,变量 variable_2 被赋值为 nameof(Enums.FormControlType.TextBox).ToLower(),在 case 语句中 nameof(Enums.FormControlType.TextBox) 的作用类似于 const,但是加上 .ToLower() 会导致错误。在我的情况下,这段代码只能在 C#7.3 中工作。 - abdul qayyum
5
也许可以使用“discard var”代替“var value”,并且测试“variable_1 == variable_2”。 case var _ when variable_1 == variable_2: - Nk54
2
由于C#7中switch语句的新模式匹配实现,您可以使用此功能。 - Jeferson Almeida
3
我宁愿使用一个庞大的 if else if else,也不想使用这个冰球解决方案。 - motcke
我宁愿使用一个庞大的if else if else,也不愿使用这个曲棍球解决方案。 - motcke

56

7
在VB.net中这种说法并不正确... 我正在尝试转换一段已经有这种情况值(基本上是方法调用)的代码。 - Moslem Ben Dhaou
6
@Moslem Ben Dhaou 是的,C# 的 Switch 语句和 VB 的 Case 语句并不相同。在 Case 语句中,您可以使用表达式(函数调用、变量等),而 C# 只能使用常量值(不能使用函数调用、变量等)。相比之下,Switch 语句的功能受到了很大限制。 - deepee1

43

在 switch 语句中,你只能匹配常量。


例子:

switch (variable1)
{
    case 1: // A hard-coded value
        // Code
        break;
    default:
        // Code
        break;
}

成功!


switch (variable1)
{
    case variable2:
        // Code
        break;
    default:
        // Code
        break;
}

CS0150 期望一个常量值。


35
补充说明: "const int myConstant = 3" 被视为常量,但 "readonly static int myReadonlyStatic = 3" 不是。 - Stachu

36
现在您可以使用 nameof:
public static void Output<T>(IEnumerable<T> dataSource) where T : class
{
    string dataSourceName = typeof(T).Name;
    switch (dataSourceName)
    {
        case nameof(CustomerDetails):
            var t = 123;
            break;
        default:
            Console.WriteLine("Test");
    }
}

nameof(CustomerDetails)基本上与字符串字面量"CustomerDetails"相同,但在编译时检查它是否引用了某个符号(以防止拼写错误)。

nameof出现在C# 6.0中,在此问题被问之后。


14

对于这个问题,您不能使用switch语句,因为case值不能被计算为表达式。您需要使用if/else语句...

public static void Output<T>(IEnumerable<T> dataSource) where T : class
{   
    dataSourceName = (typeof(T).Name);
    if(string.Compare(dataSourceName, typeof(CustomerDetails).Name.ToString(), true)==0)
    {
        var t = 123;
    }
    else if (/*case 2 conditional*/)
    {
        //blah
    }
    else
    {
        //default case
        Console.WriteLine("Test");
    }
}

我也顺手整理了你的条件语句。在调用 ToString() 后,无需将其转换为字符串。这会始终返回一个字符串。在比较字符串相等性时,请记住使用 == 运算符会导致区分大小写的比较。最好使用字符串比较 = 0 并将最后一个参数设置为区分大小写开/关。


12

至少在我尝试使用Visual Studio 2017时,这似乎对我有效。

public static class Words
{
     public const string temp = "What";
     public const string temp2 = "the";
}
var i = "the";

switch (i)
{
  case Words.temp:
    break;
  case Words.temp2:
    break;
}

3
与VS2017无关。Words.temp和Words.temp2仍然是常量。在编译Switch语句时,编译器将使用实际值替换“case values”。只要编译器能够获得常量值来使用,它就可以正常工作。 - Zé Carlos

3

在 switch 语句中,被比较的值必须是编译时常量,并且只能比较原始类型(或字符串)。如果不符合这些条件,建议使用 if 语句。

这个限制可能和 C 语言处理方式有关,即创建跳转表(因为值是编译时常量),并且不允许在 case 中使用计算出的值。


3
Johnnie,请阅读switch的msdn指南。此外,C#语言规范明确定义了编译时错误情况: • 如果switch表达式的类型是sbyte、byte、short、ushort、int、uint、long、ulong、bool、char、string或枚举类型,或者它是与这些类型之一相对应的可空类型,则该类型是switch语句的控制类型。 • 否则,必须存在一种用户定义的隐式转换(§6.4),将switch表达式的类型转换为以下可能的控制类型之一:sbyte、byte、short、ushort、int、uint、long、ulong、char、string或相应于其中一个类型的可空类型。 • 否则,如果不存在这样的隐式转换,或者存在多个这样的隐式转换,则会发生编译时错误。
希望这能有所帮助。

0

这需要最新或接近最新版本的C#。优点是在这个例子中,变量'value'可以被操作,就像这样,

   switch (args[1])

                {
                    case var value when string.Equals(value, "SELECT_ALL", StringComparison.OrdinalIgnoreCase):
{
....
break;
}
   case var value when string.Equals(value, "UNSELECT_ALL", StringComparison.OrdinalIgnoreCase):

                        {
...
...
break;
}

等等。

这会确保你永远不会匹配到错误的文字,例如在这种情况下,因为你忘记使用 ToUpper() 或其他方法...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接