【问题标题】:Switch case in C# - a constant value is expectedC# 中的 switch case - 需要一个常量值
【发布时间】:2023-04-07 17:19:01
【问题描述】:

我的代码如下:

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 语句给了我一个错误,说需要一个常量变量。请大家帮忙谢谢!

【问题讨论】:

标签: c# switch-statement


【解决方案1】:

C# switch statement limitations - why?

基本上,开关不能在 case 语句中包含评估语句。它们必须进行静态评估。

【讨论】:

  • 这在 VB.net 中是不正确的......我正在尝试转换已经具有这种 case 值的代码(基本上是方法调用)
  • @Moslem Ben Dhaou 是的 C# Switch 绝对不等同于 VB Case 语句。对于 Case 语句,您可以使用表达式(函数调用、变量等),而 C# 需要常量值(没有函数调用、变量等)。 switch 语句相对来说是相当有限的。
【解决方案2】:

您只能匹配 switch 语句中的常量。


例子:

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

成功了!


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

CS0150 需要一个常量值。

【讨论】:

  • 补充说明:“const int myConstant = 3”算作常数,但“readonly static int myReadonlyStatic = 3”不算。
【解决方案3】:

现在你可以使用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中,所以问了这个问题之后。

【讨论】:

    【解决方案4】:

    有一个与我分享的技巧(不要询问详细信息 - 无法提供,但对我有用):

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

    【讨论】:

    • 哎呀,谢谢!!!为什么这在地狱有效?!?!它也可以与 C# 8.0 变量开关 lambda 一起使用:variable_1 switchvar value when value == variable_2:
    • 在我的情况下 variable_2 是 nameof(Enums.FormControlType.TextBox).ToLower(),如果声明 nameof(Enums.FormControlType.TextBox) 用作 const 但添加到 .ToLower() 会导致错误,在我的情况下它适用于 C#7.3
    【解决方案5】:

    您不能为此使用 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() 后无需转换为字符串。无论如何,这将始终返回一个字符串。在比较字符串是否相等时,请记住使用 == 运算符将导致区分大小写的比较。最好使用字符串 compare = 0 和最后一个参数来设置区分大小写的开/关。

    【讨论】:

      【解决方案6】:

      至少在我尝试使用 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;
      }
      

      【讨论】:

      • 与 VS2017 无关。 Words.temp 和 Words.temp2 仍然是常量。编译 Switch 语句时,编译器会将“case 值”替换为其实际值。只要编译器能够得到一个常量值来使用,它就可以正常工作。
      【解决方案7】:

      switch 非常挑剔,因为 switch 中的值必须是编译时常量。并且被比较的值必须是原始的(或现在的字符串)。为此,您应该使用 if 语句。

      原因可能可以追溯到 C 处理它们的方式,因为它创建了一个跳转表(因为值是编译时常量),并且它试图通过在您的情况下不允许评估值来复制相同的语义。

      【讨论】:

        【解决方案8】:

        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 或对应于其中之一的可空类型 那些类型。

        • 否则,如果不存在这样的隐式转换,或者如果超过 如果存在这样的隐式转换,则会发生编译时错误。

        希望这会有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-06-29
          • 2013-05-15
          • 1970-01-01
          相关资源
          最近更新 更多