How to enumerate an enum

后端 未结 29 1845
深忆病人
深忆病人 2020-11-22 01:14

How can you enumerate an enum in C#?

E.g. the following code does not compile:

public enum Suit
{         


        
相关标签:
29条回答
  • 2020-11-22 01:48

    I do not hold the opinion this is better, or even good. I am just stating yet another solution.

    If enum values range strictly from 0 to n - 1, a generic alternative is:

    public void EnumerateEnum<T>()
    {
        int length = Enum.GetValues(typeof(T)).Length;
        for (var i = 0; i < length; i++)
        {
            var @enum = (T)(object)i;
        }
    }
    

    If enum values are contiguous and you can provide the first and last element of the enum, then:

    public void EnumerateEnum()
    {
        for (var i = Suit.Spade; i <= Suit.Diamond; i++)
        {
            var @enum = i;
        }
    }
    

    But that's not strictly enumerating, just looping. The second method is much faster than any other approach though...

    0 讨论(0)
  • 2020-11-22 01:50

    You won't get Enum.GetValues() in Silverlight.

    Original Blog Post by Einar Ingebrigtsen:

    public class EnumHelper
    {
        public static T[] GetValues<T>()
        {
            Type enumType = typeof(T);
    
            if (!enumType.IsEnum)
            {
                throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
            }
    
            List<T> values = new List<T>();
    
            var fields = from field in enumType.GetFields()
                         where field.IsLiteral
                         select field;
    
            foreach (FieldInfo field in fields)
            {
                object value = field.GetValue(enumType);
                values.Add((T)value);
            }
    
            return values.ToArray();
        }
    
        public static object[] GetValues(Type enumType)
        {
            if (!enumType.IsEnum)
            {
                throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
            }
    
            List<object> values = new List<object>();
    
            var fields = from field in enumType.GetFields()
                         where field.IsLiteral
                         select field;
    
            foreach (FieldInfo field in fields)
            {
                object value = field.GetValue(enumType);
                values.Add(value);
            }
    
            return values.ToArray();
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:51

    Three ways:

    1. Enum.GetValues(type) // Since .NET 1.1, not in Silverlight or .NET Compact Framework
    2. type.GetEnumValues() // Only on .NET 4 and above
    3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) // Works everywhere

    I am not sure why GetEnumValues was introduced on type instances. It isn't very readable at all for me.


    Having a helper class like Enum<T> is what is most readable and memorable for me:

    public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
    {
        public static IEnumerable<T> GetValues()
        {
            return (T[])Enum.GetValues(typeof(T));
        }
    
        public static IEnumerable<string> GetNames()
        {
            return Enum.GetNames(typeof(T));
        }
    }
    

    Now you call:

    Enum<Suit>.GetValues();
    
    // Or
    Enum.GetValues(typeof(Suit)); // Pretty consistent style
    

    One can also use some sort of caching if performance matters, but I don't expect this to be an issue at all.

    public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
    {
        // Lazily loaded
        static T[] values;
        static string[] names;
    
        public static IEnumerable<T> GetValues()
        {
            return values ?? (values = (T[])Enum.GetValues(typeof(T)));
        }
    
        public static IEnumerable<string> GetNames()
        {
            return names ?? (names = Enum.GetNames(typeof(T)));
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:54

    A simple and generic way to convert an enum to something you can interact:

    public static Dictionary<int, string> ToList<T>() where T : struct
    {
       return ((IEnumerable<T>)Enum
           .GetValues(typeof(T)))
           .ToDictionary(
               item => Convert.ToInt32(item),
               item => item.ToString());
    }
    

    And then:

    var enums = EnumHelper.ToList<MyEnum>();
    
    0 讨论(0)
  • 2020-11-22 01:56
    foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
    {
    }
    

    Note: The cast to (Suit[]) is not strictly necessary, but it does make the code 0.5 ns faster.

    0 讨论(0)
提交回复
热议问题