【问题标题】:How can I use the string value of a C# enum value in a case statement?如何在 case 语句中使用 C# 枚举值的字符串值?
【发布时间】:2010-11-19 09:11:11
【问题描述】:

我已将 C# 枚举定义为

public enum ORDER
{
    ...
    unknown,
    partial01,
    partial12,
    partial23,
}

并且可以将其值用作字符串,如下所示:

            string ss = ORDER.partial01.ToString();

但是,当我尝试在 case 语句中使用它时,它无法编译:

string value = ...
switch (value)
{
    case null:
        break;
    case "s":
        // OK
        break;
    case ORDER.partial01.ToString():
        // compiler throws "a constant value is expected"

        break;
  ...

我认为枚举是常量。我该如何解决这个问题?

(我无法将值解析为枚举,因为某些值超出了范围)

【问题讨论】:

    标签: c# string enums


    【解决方案1】:

    从 C# 6 开始,您可以使用:case nameof(SomeEnum.SomeValue):

    Nameof 在编译时被评估,只是一个与给定变量、类型或成员的(非限定)名称匹配的字符串。当然,如果您重命名枚举选项名称,它也会随之改变。

    【讨论】:

    • 优秀。我想在编译时(在属性中)使用枚举的字符串值,这为我解决了。
    • 谢谢!干净和最新的谢谢!
    【解决方案2】:

    将开关中的字符串转换为枚举值。

    (ORDER)Enum.Parse(typeof(ORDER), value, true);
    

    【讨论】:

    • 这不会处理空比较,但边缘情况可以在 case 语句之外处理。
    • 字符串值 = null; //"partial01";命令?订单=价值==空? null : (ORDER?)Enum.Parse(typeof(ORDER), value, true);
    【解决方案3】:

    枚举是一个常量,但 .ToString() 的结果不是。就编译器而言,它是一个动态值。您可能需要将您的 switch case 转换为一系列 if/else 语句

    【讨论】:

      【解决方案4】:

      作为使用if .. else 的替代方法,您可以先将字符串转换为enum。如果选项的数量很少,它可能没有多大意义:

      if (Enum.IsDefined(typeof(ORDER), value))
      {
          switch ((ORDER)Enum.Parse(typeof(ORDER), value)
          {
              case ORDER.partial01:
                  // ... 
                  break;
              case ORDER.partial12:
                  // etc
          }
      }
      else
      {
          // Handle values not in enum here if needed
      }
      

      *sigh* 要是有内置的T Enum.Parse<T>(string value) 和 TryParse 版本就好了:)

      【讨论】:

      • 广告是 Enum.TRyParse<T>(string value, out T result) msdn.microsoft.com/en-us/library/dd783499.aspx(它是 v4.5)所以在撰写本文时不可用)
      • switch ((ORDER)Enum.Parse(typeof(ORDER), value) 错过了一个结尾")"
      【解决方案5】:

      您出于某种原因将其设计为枚举,但您并没有真正将其用作枚举。为什么要获取枚举值并将其转换为字符串然后在 switch 中使用,而不是简单地使用枚举?

      您说您无法将其解析为枚举,因为某些值超出了枚举范围。那么要问的问题是,“为什么?”如果您允许未定义的值,那么拥有枚举有什么意义?当您获得未定义的值时,您希望发生什么?如果 any 未定义值相同,则可以使用默认情况。如果不是,那么您可以包含与数字表示匹配的其他案例。

      如果你真的得到了字符串,那么你可能不想使用枚举。相反,您想创建一个包含公共字符串常量的公共静态类,然后您可以在开关中使用它。这里的诀窍是评估将以区分大小写的方式进行。

      public static class Order
      {
         public const string Unknown = "Unknown";
         public const string Partial01 = "Partial01";
         public const string Partial12 = "Partial12";
         public const string Partial23 = "Partial23";
      }
      
      string value = Order.Partial01
      switch (value)
      {
         case Order.Partial01:
            break;
      
          default:
             // Code you might want to run in case you are
             // given a value that doesn't match.
             break;
      }
      

      (你可能还想清理你的外壳。)

      【讨论】:

      • 有时只检查枚举值,有时则涉及更广泛的值。我同意这可能是一个凌乱的设计,以后可能会消失。
      • @peter.murray.rust:你实际上得到了什么类型的价值?您总是将值作为字符串还是数字?如果它是数字,请保留枚举,打开值 as an enum 并使用默认情况或其他与“额外”值匹配的标记情况来执行适当的工作。如果它是字符串,那么使用我展示的方法并拥有一个包含字符串表示的静态类。您仍然可以添加与“额外”值匹配的其他标记案例。归根结底,只有当你想给数值“友好”或有意义的名字时,枚举才真正有用。
      【解决方案6】:

      正如 Thorarin 所指出的,如果您的 switch 语句只能包含 enum 案例,请先将您的 string 转换为 enum。至少从 .Net 框架 4 开始,您可以使用 Enum.TryParse()<TEnum> 定义的 here 方法并执行以下操作:

      ORDER orderEnum = ORDER.unknown;
      Enum.TryParse<ORDER>(value, out orderEnum);
      
      switch (orderEnum)
      {
          case ORDER.unknown:
              // perhaps do something to deal with cases not matching
              // to known enum values, based on the string value
              break;
          case ORDER.partial01:
          case ORDER.partial12:
          case ORDER.partial23:
              // map value to known cases, etc.
              break;
      }
      

      【讨论】:

        【解决方案7】:

        枚举值是常量,但您尝试使用方法 (ORDER.partial01.ToString()) 的结果,而不是常量。

        在我看来,最好的选择是将其切换为使用 if/else if/else 语句,而不是 switch。这将允许您使用您想要的逻辑。

        或者,如果您将字符串切换为枚举值,则可以直接打开枚举值。但是,您不能在一个开关中打开 enum + null + 其他字符串。

        【讨论】:

        • 使用ORDER可以开启null吗? ... 但是,不是字符串。
        【解决方案8】:

        你不能直接说

        case "partial01":
        

        ?

        【讨论】:

        • 然后你会硬编码和复制枚举中的值。这可能会很快变得丑陋。
        【解决方案9】:

        枚举是常量,但 ToString() 是一个返回值的函数。基于它被调用的枚举对象的实例。

        那是两条语句:

        ORDER.partial01.ToString()
        ORDER.partial02.ToString()
        

        调用同一个函数但返回两个不同的值,因此对函数 .ToString() 的调用本身不是一个常量值。

        【讨论】:

          【解决方案10】:

          就编译器而言,这不是一个静态值,因为它是一个函数调用:

          ORDER.partial01.ToString()
          

          因此,您不能将其用作 case 语句中的比较。但是,您可以这样做:

          case "partial01"
          

          这会起作用,因为枚举值和字符串是相同的。

          【讨论】:

            【解决方案11】:

            使用扩展

                  public static string ToGender(this Gender enumValue)
                    {
                        switch (enumValue)
                        {
                            case Gender.Female:
                                return "Female";
                            case Gender.Male:
                                return "Male";
                            default:
                                return null;
                        }
                    }
            

            示例

            Gender.Male.ToGender();
            

            【讨论】:

              【解决方案12】:

              只需定义一个全局变量即可

              static ORDER orderstr;
              

              现在您可以在页面的任何位置设置orderstr 的值

              public enum ORDER
              { 
                  unknown,
                  partial01,
                  partial12,
                  partial23,
              }
              
              switch (orderstr)
              {
                  case Order.Partial01:
                      break;
                  default:
                      break;
              }
              

              【讨论】:

                猜你喜欢
                • 2011-03-02
                • 2012-04-30
                • 2015-06-16
                • 2016-06-20
                • 1970-01-01
                • 2011-02-28
                • 1970-01-01
                • 2017-07-03
                • 1970-01-01
                相关资源
                最近更新 更多