【问题标题】:Key value pair as enum键值对作为枚举
【发布时间】:2011-02-08 10:41:34
【问题描述】:

我可以有一个枚举作为键值对吗?

public enum infringementCategory
{ 
    Infringement,
    OFN
}

如果我选择Infringement,我应该得到“INF0001”,如果我选择OFN,我应该得到“INF0002”

有可能吗?

【问题讨论】:

  • C# String enums的可能重复
  • 在您的情况下,枚举不是一个好的选择,请改用字典。

标签: c# .net enums


【解决方案1】:

您可以使用装饰器将字符串表示与您的枚举值相关联。检查这个问题:Enum ToString with user friendly strings

它看起来像:

public enum infringementCategory
{ 
    [Description("INF0001")]
    Infringement,
    [Description("INF0002")]
    OFN
}

看起来比使用 Dictionary 更整洁,并且需要更少的维护。

【讨论】:

    【解决方案2】:

    这些扩展怎么样:

    public static class EnumExtension
    {
        /// <summary>
        /// Gets the string of an DescriptionAttribute of an Enum.
        /// </summary>
        /// <param name="value">The Enum value for which the description is needed.</param>
        /// <returns>If a DescriptionAttribute is set it return the content of it.
        /// Otherwise just the raw name as string.</returns>
        public static string Description(this Enum value)
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }
    
            string description = value.ToString();
            FieldInfo fieldInfo = value.GetType().GetField(description);
            DescriptionAttribute[] attributes =
               (DescriptionAttribute[])
             fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
    
            if (attributes != null && attributes.Length > 0)
            {
                description = attributes[0].Description;
            }
    
            return description;
        }
    
        /// <summary>
        /// Creates an List with all keys and values of a given Enum class
        /// </summary>
        /// <typeparam name="T">Must be derived from class Enum!</typeparam>
        /// <returns>A list of KeyValuePair&lt;Enum, string&gt; with all available
        /// names and values of the given Enum.</returns>
        public static IList<KeyValuePair<Enum, string>> ToList<T>() where T : struct
        {
            var type = typeof(T);
    
            if (!type.IsEnum)
            {
                throw new ArgumentException("T must be an enum");
            }
    
            return (IList<KeyValuePair<Enum, string>>)
                    Enum.GetValues(type)
                        .OfType<Enum>()
                        .Select(e => new KeyValuePair<Enum, string>(e, e.Description()))
                        .ToArray();
        }
    
        public static T GetValueFromDescription<T>(string description) where T : struct
        {
            var type = typeof(T);
    
            if(!type.IsEnum)
            {
                throw new ArgumentException("T must be an enum");
            }
    
            foreach(var field in type.GetFields())
            {
                var attribute = Attribute.GetCustomAttribute(field,
                    typeof(DescriptionAttribute)) as DescriptionAttribute;
    
                if(attribute != null)
                {
                    if(attribute.Description == description)
                    {
                        return (T)field.GetValue(null);
                    }
                }
                else
                {
                    if(field.Name == description)
                    {
                        return (T)field.GetValue(null);
                    }
                }
            }
    
            throw new ArgumentOutOfRangeException("description");
            // or return default(T);
        }
    }
    

    有了这个,你可以像这样构建你的枚举:

    public enum Foo
    {
        [Description("Foo - Something")]
        Something,
        [Description("Foo - Anything")]
        Anything,
    }
    

    然后像这样得到你的列表:

    var list = EnumExtension.ToList<Foo>();
    

    【讨论】:

      【解决方案3】:

      您可以将标题 (INF0001)... 存储在 Dictionary&lt;infringementCategory, string&gt;

      【讨论】:

        【解决方案4】:

        见:

        public enum InfringementCategory
        {
            [EnumNamedConstant(Description = "INF0001")]
            Infringement,
        
            [EnumNamedConstant(Description = "INF0002")]
            OFN
        }
        
        public class Test{
            public void Test()
            {
                String result = InfringementCategory.Infringement.GetDescription();
            }
        }
        

        这里是扩展方法...

        #region [ EnumNamedConstantAttribute ]
        [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
        public class EnumNamedConstantAttribute : Attribute
        {
            public string Description { get; set; }
            public string Value { get; set; }
        }
        #endregion
        
        
        #region EnumUtilities
        public static class EnumUtilities
        {
            #region [ + Extension Methods ]
        
            #region [ GetDescription ]
        
            public static string GetDescription(this Enum constant)
            {
                return EnumUtilities.GetEnumNamedConstantAttribute(constant).Description;
            }
            #endregion
        
            #region [ GetStringValue ]
        
            public static string GetStringValue(this Enum constant)
            {
                return GetEnumNamedConstantValue(constant);
            }
            #endregion
        
            #endregion
        
            #region [ + Static Methods ]
        
            #region [ GetEnumerable ]
        
            public static IEnumerable<EnumNamedConstantAttribute> GetEnumerable<T>()
            {
                T instancia = Activator.CreateInstance<T>();
        
                FieldInfo[] objInfos = instancia.GetType().GetFields(BindingFlags.Public | BindingFlags.Static);
                foreach (FieldInfo objFileInfo in objInfos)
                {
                    Enum constant = (Enum)objFileInfo.GetValue(objFileInfo);
                    if (objFileInfo.GetCustomAttributes(typeof(EnumNamedConstantAttribute), false).Length != 0)
                    {
                        yield return new EnumNamedConstantAttribute()
                        {
                            Description = EnumUtilities.GetEnumNamedConstantAttribute(constant).Description,
                            Value = GetEnumNamedConstantValue(constant)
                        };
                    }
                }
            }
            #endregion
        
            #endregion
        
            #region [ + Privates ]
        
            #region [ GetEnumNamedConstantAttribute ]
            private static EnumNamedConstantAttribute GetEnumNamedConstantAttribute(Enum constant)
            {
                FieldInfo[] objInfos = constant.GetType().GetFields(BindingFlags.Public | BindingFlags.Static);
                foreach (FieldInfo objFileInfo in objInfos)
                {
                    Enum constantItem = (Enum)objFileInfo.GetValue(objFileInfo);
                    if (constantItem.GetHashCode().Equals(constant.GetHashCode()))
                    {
                        object[] attributes = objFileInfo.GetCustomAttributes(typeof(EnumNamedConstantAttribute), false);
        
                        if (attributes.Length > 0)
                            return (EnumNamedConstantAttribute)attributes[0];
                    }
                }
                return null;
            }
            #endregion
        
            #region [ GetEnumNamedConstantValue ]
            private static string GetEnumNamedConstantValue(Enum constant)
            {
                string sValue = (constant.GetHashCode()).ToString();
                EnumNamedConstantAttribute objRet = EnumUtilities.GetEnumNamedConstantAttribute(constant);
                if (objRet != null)
                {
                    String sAux = objRet.Value;
                    if (!String.IsNullOrEmpty(sAux))
                        sValue = objRet.Value;
                }
                return sValue;
            }
            #endregion
        
            #endregion
        }
        #endregion
        

        【讨论】:

          【解决方案5】:

          更新:
          感谢 Oliver 指出System.Component.DescriptionAttribute。操作方法如下:

          public enum infringementCategory
          {
              [Description("INF0001")]
              Infringement,
              [Description("INF0002")]
              OFN
          }
          
          public static class DescriptionExtensions
          {
              public static string GetDescriptionValue(this Enum value)
              {
                  // Get the type
                  Type type = value.GetType();
          
                  // Get fieldinfo for this type
                  FieldInfo fieldInfo = type.GetField(value.ToString());
          
                  // Get the stringvalue attributes
                  DescriptionAttribute[] attribs = fieldInfo.GetCustomAttributes(
                      typeof(DescriptionAttribute), false) as DescriptionAttribute[];
          
                  // Return the first if there was a match.
                  return attribs.Length > 0 ? attribs[0].Description : null;
              }
          }
          
          public class Program
          {
              static void Main(string[] args)
              {
                  infringementCategory category = infringementCategory.OFN;
                  string description = category.GetDescriptionValue();
              }
          }
          

          【讨论】:

          • 如果你可以使用DescriptionAttribute,为什么还要使用自写属性?
          • @Oliver 我同意,虽然那篇博文也有一个扩展方法来获取属性值
          【解决方案6】:

          您有多种选择:

          1. 建议使用 vc74 的字典。这是有效的,并且可以将您的枚举与属性分离。

          2. switch 语句

          3. 如果您只想与每个相关联的是一个整数,您可以使用:

             public enum InfringementCategory
             { 
                 Infringement = 1,
                 OFN = 2
             }
            

            然后将(int)myEnum放入String.Format中,变成你想要的形式的字符串。

          4. 属性

            public enum InfringementCategory
            { 
                [InfID("INF0001")]Infringement,
                [InfID("INF0002")]OFN
            }
            

            为了提高性能,您可以使用一次反射来填充字典。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-03-02
            • 1970-01-01
            • 2018-10-30
            • 2019-02-17
            • 1970-01-01
            • 2019-08-16
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多