【问题标题】:Possible to have strings for enums?可能有枚举字符串?
【发布时间】:2009-10-16 17:48:30
【问题描述】:

我想要一个枚举,如下所示:

enum FilterType
{
   Rigid = "Rigid",
   SoftGlow = "Soft / Glow",
   Ghost = "Ghost",
}

如何做到这一点?有一个更好的方法吗?它将用于将被序列化/反序列化的对象的实例。它还将填充一个下拉列表。

【问题讨论】:

    标签: c# .net enums


    【解决方案1】:
    using System.ComponentModel;   
    enum FilterType
    {
        [Description("Rigid")]
        Rigid,
        [Description("Soft / Glow")]
        SoftGlow,
        [Description("Ghost")]
        Ghost ,
    }
    

    你可以这样获取价值

    public static String GetEnumerationDescription(Enum e)
    {
      Type type = e.GetType();
      FieldInfo fieldInfo = type.GetField(e.ToString());
      DescriptionAttribute[] da = (DescriptionAttribute[])(fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false));
      if (da.Length > 0)
      {
        return da[0].Description;
      }
      return e.ToString();
    }
    

    【讨论】:

    • 不错的方法。您甚至可以将其作为所有枚举的扩展方法。
    • 谢谢.. 我在当前项目中使用了很多静态方法来处理这样的枚举。我从没想过使用扩展方法。我得试试看
    • 通过在 [System.Xml.Serialization.XmlEnum("Rigid")] ...[Description("刚性")]刚性,...等
    【解决方案2】:

    不,但是如果您想限定“const”字符串的范围并像枚举一样使用它们,这就是我所做的:

    public static class FilterType
    {
       public const string Rigid = "Rigid";
       public const string SoftGlow =  "Soft / Glow";
       public const string Ghost ="Ghost";
    }
    

    【讨论】:

    • 这也是我过去的做法,适用于大多数用途。
    • 这种方法的缺点是我看不到您如何自动填充下拉列表。通过一些工作,您至少可以选择迭代枚举的值。
    • 或者你可以定义一个静态字符串 Values[] 数组。
    • DV for NO in ..."不,但如果你想限定 "const" 字符串 ..."
    【解决方案3】:

    如果您对扩展方法感到满意,您可以轻松地做您想做的事情:

    //Can return string constants, the results of a Database call, 
    //or anything else you need to do to get the correct value 
    //(for localization, for example)
    public static string EnumValue(this MyEnum e) {
        switch (e) {
            case MyEnum.First:
                return "First Friendly Value";
            case MyEnum.Second:
                return "Second Friendly Value";
            case MyEnum.Third:
                return "Third Friendly Value";
        }
        return "Horrible Failure!!";
    }
    

    这样你就可以做到:

    Private MyEnum value = MyEnum.First;
    Console.WriteLine(value.EnumValue());
    

    【讨论】:

      【解决方案4】:

      不,但你可以这样作弊:

      public enum FilterType{
         Rigid,
         SoftGlow,
         Ghost
      }
      

      然后,当您需要他们的字符串值时,您可以执行FilterType.Rigid.ToString()

      【讨论】:

      • 这样做(我也犯了罪)显示没有空格/特殊字符的用户文本(SoftGlow,而不是“Soft / Glow”),我确定他想要能够做到。
      【解决方案5】:

      枚举总是链接到一个整数值。所以不行。 可以通过FilterType.Rigid.ToString()获取字符串值,虽然不能直接本地化。

      【讨论】:

        【解决方案6】:

        您可以像这样将枚举名称作为字符串获取

        FilterType myType = FilterType.Rigid;
        String strType = myType.ToString();
        

        但是,您可能会被 Camel Case/Hungarian 表示法困住,但您可以使用这样的方法轻松地将其转换为对用户更友好的字符串(不是最漂亮的解决方案,我将不胜感激有关优化此的输入) :

        Public Shared Function NormalizeCamelCase(ByVal str As String) As String
        
            If String.IsNullOrEmpty(str) Then
                Return String.Empty
            End If
        
            Dim i As Integer = 0
            Dim upperCount As Integer = 0
            Dim otherCount As Integer = 0
            Dim normalizedString As String = str
        
            While i < normalizedString.Length
        
                If Char.IsUpper(normalizedString, i) Then
                    ''Current char is Upper Case
                    upperCount += 1
                    If i > 0 AndAlso Not normalizedString(i - 1).Equals(" "c) Then
                        ''Current char is not first and preceding char is not a space
                        ''...insert a space, move to next char
                        normalizedString = normalizedString.Insert(i, " ")
                        i += 1
                    End If
                ElseIf Not Char.IsLetter(normalizedString, i) Then
                    otherCount += 1
                End If
        
                ''Move to next char
                i += 1
        
            End While
        
            If upperCount + otherCount = str.Length Then
                ''String is in all caps, return original string 
                Return str
            Else
                Return normalizedString
            End If
        
        End Function
        

        如果这还不够漂亮,您可能需要查看自定义属性,可以使用反射检索...

        【讨论】:

          【解决方案7】:

          在 System.ComponentModel 命名空间中有一个类 DescriptionAttribute 在这里工作得很好。

          enum FilterType
          {
             Rigid,
             [Description("Soft / Glow")]
             SoftGlow,
             Ghost,
          }
          

          然后获取描述并故障转移到 ToString()

          var descriptionAttribute = Value.GetType()
           .GetField(Value.ToString())
           .GetCustomAttributes(typeof(DescriptionAttribute), false)
           .OfType <DescriptionAttribute>()
           .FirstOrDefault()??new DescriptionAttribute(Value.ToString());
          

          【讨论】:

            【解决方案8】:

            这是不可能的。 C# 只允许整数枚举类型(int、short、long 等)。您可以创建一个轻量级的“类枚举”类或使用静态常量。

            static class FilterTypes
            {
                public const string Rigid = "Rigid";
                // ...
            }
            
            // or ...
            
            class FilterType
            {
                static readonly FilterType RigidFilterType = new FilterType("Rigid");
            
                string name;
            
                FilterType(string name)  // private constructor
                {
                    this.name = name;
                }
            
                public static FilterType Rigid
                {
                    get { return FilterType.RigidFilterType; }
                }
            
                // ...
            }
            

            【讨论】:

              【解决方案9】:

              这不是完全可能的。但是,您可以使用数组来伪造它。

              首先,以常规方式创建枚举:

              public enum Regexs
              { 
                 ALPHA = 0, 
                 NUMERIC = 1, 
                 etc.. 
              }
              

              然后你创建一个数组来保存与枚举值对应的值:

              private static string[] regexs = new string[]
              {
                 "[A-Za-z]",
                 "[0-9]",
                 "etc"...
              }
              

              然后你可以通过枚举值访问你的字符串:

              public void runit(Regexs myregexEnum)
              {
                  Regex regex = new Regex( regexs [(int)myregexEnum] );
              }
              

              【讨论】:

              • 我认为这个解决方案对已经(两年半)接受的答案没有任何好处,因为现在如果您对枚举进行任何更改,您必须保持两个位置同步.
              【解决方案10】:

              不,这是不可能的。

              枚举的批准类型是 字节,sbyte,短,ushort,int,uint, long 或 ulong。

              但是,您可以使用 Enum 类检索声明的枚举名称:

              string name = Enum.GetName(typeof(FilterType), FilterType.Rigid);
              

              如果这对您不起作用,则可能是在一个类中收集的字符串常量集合。

              【讨论】:

                【解决方案11】:

                您可以在值上使用属性

                [System.ComponentModel.Description("Rigid")]
                

                示例:

                 enum FilterType
                {
                   [System.ComponentModel.Description("Rigid")]
                   Rigid,
                    [System.ComponentModel.Description("Soft / Glow")]
                   SoftGlow,
                    [System.ComponentModel.Description("Ghost")]
                   Ghost
                }
                

                并使用反射来获取描述。

                枚举扩展方法:

                public static string GetDescription(this Enum en)
                    {
                        var type = en.GetType();
                        var memInfo = type.GetMember(en.ToString());
                
                        if (memInfo != null && memInfo.Length > 0)
                        {
                            var attrs = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
                            if (attrs != null && attrs.Length > 0)
                                return ((DescriptionAttribute)attrs[0]).Description;
                        }
                        return en.ToString();
                    }
                

                使用它:

                FilterType = FilterType.Rigid;
                            string description= result.GetDescription();
                

                【讨论】:

                  【解决方案12】:

                  按照 Shaun Bowe 的示例,您也可以在 C# 3 中使用 enum 的扩展方法执行此操作(我没有想出,也无法记住我在哪里做的)。

                  创建一个属性:

                  public class DisplayTextAttribute : Attribute {
                    public DisplayTextAttribute(String text) {
                    Text = text;
                    }
                    public string Text { get; set; }
                  }
                  

                  创建一个扩展:

                  public static class EnumHelpers {
                    public static string GetDisplayText(this Enum enumValue) {
                      var type = enumValue.GetType();
                      MemberInfo[] memberInfo = type.GetMember(enumValue.ToString());
                  
                      if (memberInfo == null || memberInfo.Length == 0)
                        return enumValue.ToString();
                  
                      object[] attributes = memberInfo[0].GetCustomAttributes(typeof(DisplayTextAttribute), false);
                      if (attributes == null || attributes.Length == 0)
                        return enumValue.ToString();
                  
                      return ((DisplayTextAttribute)attributes[0]).Text;
                    }
                  }
                  

                  我发现这是一个非常整洁的解决方案。 在您的枚举中添加以下内容:

                  enum FilterType{
                    Rigid,
                    [DisplayText("Soft / Glow")]
                    SoftGlow,
                    Ghost
                  }
                  

                  然后您可以访问FilterType.GetDisplayText(),它将为未归属的枚举拉回字符串,为具有属性的枚举拉回 displayText。

                  【讨论】:

                  • 有趣的方法。只需确保不要在“高性能”路径中使用此代码,因为进行反射调用非常昂贵。
                  猜你喜欢
                  • 2012-06-26
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-06-07
                  • 2014-07-23
                  相关资源
                  最近更新 更多