【问题标题】:C# numeric enum value as stringC# 数字枚举值作为字符串
【发布时间】:2011-03-27 13:26:13
【问题描述】:

我有以下枚举:

public enum Urgency {
    VeryHigh = 1,
    High     = 2,
    Routine  = 4
}

我可以像这样获取 枚举“值”作为字符串

((int)Urgency.Routine).ToString() // returns "4"  

注意:这不同于:

Urgency.Routine.ToString() // returns "Routine"
(int)Urgency.Routine       // returns 4

有没有一种方法可以创建扩展类或静态实用程序类,以提供一些语法糖? :)

【问题讨论】:

  • 您能更准确地了解您要查找的内容吗?
  • 即enumValue.ToValueString() == int 值?
  • 底层 int 值 - 但作为字符串(而不是作为字符串的枚举)而不是记住转换为 int 然后转换为字符串的古老语法,而是一个静态类,其方法采用any 枚举值会使其更易于使用。我怀疑该语言可能不支持我所追求的。
  • .. 认为我做了你想要的。

标签: c# enums return-value return-type


【解决方案1】:

一个简单的方法

((Urgency)4).ToString() // returns "Routine"

【讨论】:

    【解决方案2】:

    很棒的东西...我现在为我的项目添加了一个扩展方法

    public static class EnumExtensions 
    { 
        public static string NumberString(this Enum enVal) 
        { 
            return enVal.ToString("D"); 
        }
    } 
    

    现在我可以通过调用 Urgency.Routine.NumberString(); 来获取 int 值 - 作为字符串 - 感谢 Frankentosh 和 Jon :)

    【讨论】:

      【解决方案3】:

      为了获得更多“人类可读”的枚举描述(例如,您的示例中的“非常高”而不是“非常高”),我使用如下属性修饰了枚举值:

      public enum MeasurementType
      {
          Each,
      
          [DisplayText("Lineal Metres")]
          LinealMetre,
      
          [DisplayText("Square Metres")]
          SquareMetre,
      
          [DisplayText("Cubic Metres")]
          CubicMetre,
      
          [DisplayText("Per 1000")]
          Per1000,
      
          Other
      }
      
      
      public class DisplayText : Attribute
      {
      
          public DisplayText(string Text)
          {
              this.text = Text;
          }
      
      
          private string text;
      
      
          public string Text
          {
              get { return text; }
              set { text = value; }
          }
      }
      

      然后,使用这样的扩展方法:

          public static string ToDescription(this Enum en)
          {
      
              Type type = en.GetType();
      
              MemberInfo[] memInfo = type.GetMember(en.ToString());
      
              if (memInfo != null && memInfo.Length > 0)
              {
      
                  object[] attrs = memInfo[0].GetCustomAttributes(
                                                typeof(DisplayText),
      
                                                false);
      
                  if (attrs != null && attrs.Length > 0)
      
                      return ((DisplayText)attrs[0]).Text;
      
              }
      
              return en.ToString();
      
          }
      

      然后你就可以打电话了

      myEnum.ToDescription()
      以将您的枚举显示为更具可读性的文本。

      【讨论】:

      • 我也做过类似的事情,但通常只是依赖于骆驼套管的约定。虽然没有按照问题的要求做。
      • 谢谢 - 但不返回 int 值 - 作为字符串 :)
      • 您没有添加DisplayText 属性的声明。可以加一下吗?
      • 谢谢斯图尔特。它现在正在工作。不幸的是,我不能给你多个 +1,所以我想我之前的一个就足够了。
      • 我认为这可能是一位前同事这样做,因为我多次使用相同的解决方案,甚至调用属性 DisplayText - 尽管我也玩过进一步的装饰枚举所以我通过“GetAttrib()”函数走很长一段路 - 返回 (TAttrib)enumValue.GetType().GetMember(enumValue.ToString()).First().GetCustomAttributes(typeof(TAttrib), false) .FirstOrDefault();
      【解决方案4】:

      如果您愿意,可以使扩展方法适用于所有枚举:

      public static string ToValueString(this Enum enumValue) 
      {
          if (enumValue.GetType().GetEnumUnderlyingType() == typeof(int))
              return ((int)(object)enumValue).ToString();
          else if (enumValue.GetType().GetEnumUnderlyingType() == typeof(byte))
              return ((byte)(object)enumValue).ToString();
          ... 
      }        
      

      【讨论】:

      • +1:有趣……但同时看到双重演员有点不寻常。好把戏。 :) 可以使用Enum 而不是T where T : struct
      • 你是对的。不知道为什么我认为这在这种情况下很有帮助。更改它以反映您的建议。
      【解决方案5】:

      如果您只想处理这个枚举,请使用 Mark Byer 的解决方案。

      对于更通用的解决方案:

      public static string NumberString(this Enum enVal) 
      {
          return Convert.ToDecimal(enVal).ToString("0");
      }
      

      转换为十进制意味着您不需要显式处理 8 种不同的允许的基础整数类型,因为它们都无损地转换为十进制,但彼此之间不转换(ulong 和 long 不会在彼此之间进行无损转换,而是两者都可以处理所有其余的)。这样做可能会更快(尤其是如果您在比较顺序中选择得很好),但会更加冗长,收获相对较小。

      编辑:

      虽然上面的不如弗兰肯托什,但弗兰肯托什看穿了真正的问题,并且非常雄辩地解决了它。

      【讨论】:

        【解决方案6】:

        您应该能够使用 Enums ToString 方法的重载来给它一个格式字符串,这会将枚举的值打印为字符串。

        public static class Program
        {
            static void Main(string[] args)
            {
                var val = Urgency.High;
                Console.WriteLine(val.ToString("D")); 
            }
        }
        
        public enum Urgency 
        { 
            VeryHigh = 1,
            High = 2,
            Low = 4
        }
        

        【讨论】:

        • 波什。美丽的简单。让我想删除我的答案! +1
        • 是的,在提供相同的结果和不同的查询方法时,横向思考很好。代码public static string NumberString(this Enum enVal){return enVal.ToString("D");} 应该是您的想法并将其转化为所要求的扩展方法。
        • 好东西......请参阅下面的答案
        • 我喜欢这个而不是另一个使用扩展方法的。通过创建扩展方法,您只需为代码添加不必要的依赖项。记住你的代码越少依赖越好!!
        • 应用于多个枚举值(示例):new[] { ProductStatus.Open, ProductStatus.Deprecated }.Select(s => s.ToString("D"))
        【解决方案7】:

        稍微反思一下怎么样?应该适用于所有底层类型。

        public static class EnumTools
        {
            public static string ToRawValueString(this Enum e)
            {
                return e
                    .GetType()
                    .GetFields(BindingFlags.Public | BindingFlags.Static)
                    .First(f => f.Name==e.ToString())
                    .GetRawConstantValue()
                    .ToString();
            }
        }
        

        然后:

        Console.WriteLine(Urgency.High.ToRawValueString()); //Writes "2"
        

        【讨论】:

        • First() 如果在枚举中没有定义的值匹配该值,则将失败,特别常见于标志枚举并且在其他情况下可能(只要Enum.IsDefined(e.GetType(), e)返回false)这需要为了在这种情况下更具防御性,然后回退到不会在有效(如果尴尬)值上失败将是使用非反射方法,当您重构时意味着您将删除反射位除非它被证明要快得多。
        • @Jon :我看不出 Enum 的类型怎么可能不包含它的条目。我错过了什么?编辑:明白了,枚举可能是 ORed 标志。我同意你的评论。
        • 这是最常见的情况。将基础类型的任何值强制转换为枚举类型也是有效的,因此存在 Enum.IsDefined() 以允许捕获可能是方法的无效参数或属性的无效值的情况。
        【解决方案8】:

        您可以为您的特定类型编写扩展方法:

        public static class UrgencyExtension
        {
            public static string ToIntegerString(this Urgency u)
            {
                return ((int)u).ToString();
            }
        }
        

        如下使用:

        Urgency u = Urgency.Routine;
        string s = u.ToIntegerString();
        

        【讨论】:

          猜你喜欢
          • 2011-10-03
          • 1970-01-01
          • 1970-01-01
          • 2011-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多