.net how - C#에서 열거 형을 어떻게 열거합니까?





to use (22)


나는 그것이 조금 지저분한 것을 알고있다. 그러나 만일 당신이 one-liners의 팬이라면, 여기는 하나 다.

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));

C #에서 열거 형을 어떻게 열거 할 수 있습니까?

예를 들어 다음 코드는 컴파일되지 않습니다.

public enum Suit 
{
    Spades,
    Hearts,
    Clubs,
    Diamonds
}

public void EnumerateAllSuitsDemoMethod() 
{
    foreach (Suit suit in Suit) 
    {
        DoSomething(suit);
    }
}

그리고 다음과 같은 컴파일 타임 오류가 발생합니다.

'Suit'는 '유형'이지만 '변수'처럼 사용됩니다.

두 번째 키워드 인 Suit 키워드에서는 실패합니다.




네가 사용할 수 있다고 생각해.

Enum.GetNames(Suit)



foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

나는 이것이 아주 천천히 느리다는 모호한 소문을 들었다. 누구 알아? - 오리온 에드워즈, 2003 년 10 월 15 일 1:31 7

배열을 캐싱하면 속도가 상당히 빨라질 것이라고 생각합니다. 매번 리플렉션을 통해 새로운 배열을 얻는 것 같습니다. 차라리:

Array enums = Enum.GetValues(typeof(Suit));
foreach (Suit suitEnum in enums) 
{
    DoSomething(suitEnum);
}

적어도 조금 더 빨랐어 요?




Enum 을 반복하는 두 가지 방법이 있습니다.

1. var values =  Enum.GetValues(typeof(myenum))
2. var values =  Enum.GetNames(typeof(myenum))

첫 번째는 object 의 배열에서 값을 폼에 제공하고 두 번째는 String 배열로 값을 제공합니다.

foreach 루프에서 다음과 같이 사용하십시오.

foreach(var value in values)
{
    //Do operations here
}



나는 GetValues() 가 루프를 가질 때마다 호출되지 않기 때문에 이것이 다른 제안보다 더 효율적이라고 생각한다. 또한 더 간결합니다. Suitenum 이 아니면 컴파일 타임 오류가 발생합니다.

EnumLoop<Suit>.ForEach((suit) => {
    DoSomethingWith(suit);
});

EnumLoop 에는 완전히 일반적인 정의가 있습니다.

class EnumLoop<Key> where Key : struct, IConvertible {
    static readonly Key[] arr = (Key[])Enum.GetValues(typeof(Key));
    static internal void ForEach(Action<Key> act) {
        for (int i = 0; i < arr.Length; i++) {
            act(arr[i]);
        }
    }
}



foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}



일부 .NET Framework 버전은 Enum.GetValues 지원하지 않습니다. Ideas 2.0 의 좋은 해결 방법은 다음과 같습니다 . Compact Framework의 Enum.GetValues :

public List<Enum> GetValues(Enum enumeration)
{
   List<Enum> enumerations = new List<Enum>();
   foreach (FieldInfo fieldInfo in enumeration.GetType().GetFields(
         BindingFlags.Static | BindingFlags.Public))
   {
      enumerations.Add((Enum)fieldInfo.GetValue(enumeration));
   }
   return enumerations;
}

reflection 을 포함하는 모든 코드와 마찬가지로, 한 번만 실행되고 결과가 캐시되도록 조치를 취해야합니다.




유형이 enum 형이 될 것이라는 것을 알고 있지만 컴파일 타임에 정확한 유형이 무엇인지 알 수 없다면 어떻게 될까요?

public class EnumHelper
{
    public static IEnumerable<T> GetValues<T>()
    {
        return Enum.GetValues(typeof(T)).Cast<T>();
    }

    public static IEnumerable getListOfEnum(Type type)
    {
        MethodInfo getValuesMethod = typeof(EnumHelper).GetMethod("GetValues").MakeGenericMethod(type);
        return (IEnumerable)getValuesMethod.Invoke(null, null);
    }
}

getListOfEnum 메소드는 리플렉션을 사용해 모든 enum 형을 취해, 모든 enum 치의 IEnumerable 를 돌려줍니다.

용법:

Type myType = someEnumValue.GetType();

IEnumerable resultEnumerable = getListOfEnum(myType);

foreach (var item in resultEnumerable)
{
    Console.WriteLine(String.Format("Item: {0} Value: {1}",item.ToString(),(int)item));
}



Silverlight에서 Enum.GetValues() 를 얻지 못합니다.

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();
    }
}



메소드에 public static IEnumerable<T> GetValues<T>() 를 클래스에 추가하십시오.

public static IEnumerable<T> GetValues<T>()
{
    return Enum.GetValues(typeof(T)).Cast<T>();
}

열거 형을 호출하고 전달하면 이제 foreach 사용하여 foreach 할 수 있습니다.

 public static void EnumerateAllSuitsDemoMethod()
 {
     // custom method
     var foos = GetValues<Suit>(); 
     foreach (var foo in foos)
     {
         // Do something
     }
 }



Cast<T> 사용하는 사람이없는 이유는 무엇입니까?

var suits = Enum.GetValues(typeof(Suit)).Cast<Suit>();

거기에 IEnumerable<Suit> 있습니다.




열거 형을 상호 작용할 수있는 것으로 변환하는 간단하고 일반적인 방법 :

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());
}

그리고:

var enums = EnumHelper.ToList<MyEnum>();



쉽게 열거 형 사용법을위한 약간 연장을 만들었다, 어쩌면 누군가는 그것을 사용할 수있다 ...

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this Enum value)
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all items for an enum type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>() where T : struct
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all combined items from an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    /// <example>
    /// Displays ValueA and ValueB.
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// foreach (var item in dummy.GetAllSelectedItems<EnumExample>())
    /// {
    ///    Console.WriteLine(item);
    /// }
    /// </code>
    /// </example>
    public static IEnumerable<T> GetAllSelectedItems<T>(this Enum value)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);

        foreach (object item in Enum.GetValues(typeof(T)))
        {
            int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture);

            if (itemAsInt == (valueAsInt & itemAsInt))
            {
                yield return (T)item;
            }
        }
    }

    /// <summary>
    /// Determines whether the enum value contains a specific value.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="request">The request.</param>
    /// <returns>
    ///     <c>true</c> if value contains the specified value; otherwise, <c>false</c>.
    /// </returns>
    /// <example>
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// if (dummy.Contains<EnumExample>(EnumExample.ValueA))
    /// {
    ///     Console.WriteLine("dummy contains EnumExample.ValueA");
    /// }
    /// </code>
    /// </example>
    public static bool Contains<T>(this Enum value, T request)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
        int requestAsInt = Convert.ToInt32(request, CultureInfo.InvariantCulture);

        if (requestAsInt == (valueAsInt & requestAsInt))
        {
            return true;
        }

        return false;
    }
}

enum 자체는 FlagsAttribute 로 장식되어야합니다.

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}



또한 리플렉션을 사용하여 열거 형의 public 정적 멤버에 직접 바인딩 할 수 있습니다.

typeof(Suit).GetMembers(BindingFlags.Public | BindingFlags.Static)
    .ToList().ForEach(x => DoSomething(x.Name));



도대체 내가 두 개의 펜스를 던져 버릴거야. 가장 간단한 확장자

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this Enum value)
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

간단하고 @ Jeppe-Stig-Nielsen 님의 덧글을 빨리 정리하십시오.




컴팩트 프레임 워크 (3.5)에서 작동 하고 컴파일 타임에 유형 검사 지원하는 내 솔루션을 추가하기 만하면됩니다.

public static List<T> GetEnumValues<T>() where T : new() {
    T valueType = new T();
    return typeof(T).GetFields()
        .Select(fieldInfo => (T)fieldInfo.GetValue(valueType))
        .Distinct()
        .ToList();
}

public static List<String> GetEnumNames<T>() {
    return typeof (T).GetFields()
        .Select(info => info.Name)
        .Distinct()
        .ToList();
}

- 누군가 T valueType = new T() 제거하는 방법을 알고 있다면, 해결책을 T valueType = new T() 기쁩니다.

호출은 다음과 같습니다.

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();



다음은 DDL에 대한 선택 옵션을 만드는 작업 예제입니다.

var resman = ViewModelResources.TimeFrame.ResourceManager;

ViewBag.TimeFrames = from MapOverlayTimeFrames timeFrame 
      in Enum.GetValues(typeof(MapOverlayTimeFrames))
      select new SelectListItem
      {
         Value = timeFrame.ToString(),
         Text = resman.GetString(timeFrame.ToString()) ?? timeFrame.ToString()
      };



세 가지 방법 :

1. Enum.GetValues(type) //since .NET 1.1, not in silverlight or compact framewok
2. type.GetEnumValues() //only on .NET 4 and above
3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) //works everywhere

GetEnumValues 가 type 인스턴스에 도입 된 이유는 무엇인지 잘 모릅니다. 전혀 읽을 수 없습니다.

Enum<T> 형 ( Enum<T> )과 같은 도우미 클래스를 갖는 것이 가장 읽기 쉽고 기억하기 쉬운 클래스입니다.

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));
    }
}

이제 전화주세요 :

Enum<Suit>.GetValues();
//or
Enum.GetValues(typeof(Suit)); //pretty consistent style

퍼포먼스가 중요하다면 캐싱을 사용할 수도 있지만, 이것이 전혀 문제가되지는 않을 것이라고 생각합니다.

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)));
    }
}



이 질문은 " C # Step by Step 2013 "10 장에 나와 있습니다.

저자는 double for-loop를 사용하여 한 쌍의 열거자를 반복합니다 (카드의 전체 데크 만들기).

class Pack
{
    public const int NumSuits = 4;
    public const int CardsPerSuit = 13;
    private PlayingCard[,] cardPack;

    public Pack()
    {
        this.cardPack = new PlayingCard[NumSuits, CardsPerSuit];
        for (Suit suit = Suit.Clubs; suit <= Suit.Spades; suit++)
        {
            for (Value value = Value.Two; value <= Value.Ace; value++)
            {
                cardPack[(int)suit, (int)value] = new PlayingCard(suit, value);
            }
        }
    }
}

이 경우 SuitValue 는 둘 다 열거 형입니다.

enum Suit { Clubs, Diamonds, Hearts, Spades }
enum Value { Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace}

PlayingCardSuitValue 이 정의 된 카드 객체입니다.

class PlayingCard
{
    private readonly Suit suit;
    private readonly Value value;

    public PlayingCard(Suit s, Value v)
    {
        this.suit = s;
        this.value = v;
    }
}



저는 이것이 더 낫다는 의견이나 다른 좋은 해결책을 말하는 좋은 의견을 갖고 있지 않습니다.

enum 값이 0에서 n - 1까지의 범위를 가지면 일반적인 대안 :

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

열거 형 값이 인접하고 열거 형의 첫 번째 요소와 마지막 요소를 제공 할 수있는 경우 다음을 수행하십시오.

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

하지만 이것은 반복적으로 열거 된 것이 아닙니다. 두 번째 방법은 다른 어떤 방법보다 훨씬 빠릅니다 ...




ToString ()을 사용하여 깃발 배열을 분할하고 구문 분석합니다.

[Flags]
public enum ABC {
   a = 1,
   b = 2,
   c = 4
};

public IEnumerable<ABC> Getselected (ABC flags)
{
   var values = flags.ToString().Split(',');
   var enums = values.Select(x => (ABC)Enum.Parse(typeof(ABC), x.Trim()));
   return enums;
}

ABC temp= ABC.a | ABC.b;
var list = getSelected (temp);
foreach (var item in list)
{
   Console.WriteLine(item.ToString() + " ID=" + (int)item);
}



플래그를 사용하면 열거 형 내부에서 비트 마스킹을 사용할 수 있습니다. 이를 통해 열거 값을 유지하면서 열거 값을 결합 할 수 있습니다.

[Flags]
public enum DashboardItemPresentationProperties : long
{
    None = 0,
    HideCollapse = 1,
    HideDelete = 2,
    HideEdit = 4,
    HideOpenInNewWindow = 8,
    HideResetSource = 16,
    HideMenu = 32
}




c# .net enums enumeration