[c#] 열거 형을 반복하는 방법은 무엇입니까?


Answers

값보다 각 열거 형의 이름을 실제로 인쇄하고 싶은 것처럼 보입니다. Enum.GetNames() 가 올바른 접근 방법 인 것 같습니다.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (string name in Enum.GetNames(typeof(Suits)))
    {
        System.Console.WriteLine(name);
    }
}

그런데 값을 증가시키는 것은 열거 형의 값을 열거하는 좋은 방법이 아닙니다. 대신이 작업을 수행해야합니다.

대신 Enum.GetValues(typeof(Suit)) 사용합니다.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (var suit in Enum.GetValues(typeof(Suits)))
    {
        System.Console.WriteLine(suit.ToString());
    }
}
Question

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

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

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

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

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

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

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




enum 유형은 값을 "열거"하는 컨테이너가 아니라 해당 유형의 변수에 대해 가능한 값을 열거 하여 정의되기 때문에 "열거 유형"이라고합니다.

실제로 enum 유형은 "기본"정수 유형으로 간주되므로 각 enum 값은 정수 값에 해당합니다 (일반적으로 암시 적이지만 수동으로 지정할 수 있음). C #을 설계했습니다. 어떤 식 으로든 그 형식의 정수를 "명명 된"값이 아니더라도 enum 변수에 채울 수 있습니다.

이름에서 알 수 있듯이 System.Enum.GetNames 메서드 를 사용하여 열거 형 값의 이름 인 문자열 배열을 검색 할 수 있습니다.

편집 : 대신 System.Enum.GetValues 메서드를 제안해야합니다. 죄송합니다.




이 질문은 " 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;
    }
}



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



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

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 님의 덧글을 빨리 정리하십시오.




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

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



컴팩트 프레임 워크 (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>();



메소드에 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
     }
 }



public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}



저는 이것이 더 낫다는 의견을 말하지 않습니다. 또 다른 해결책을 말하면서도 좋습니다.

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

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




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



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

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

거기에 IEnumerable<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 을 포함하는 모든 코드와 마찬가지로, 한 번만 실행되고 결과가 캐시되도록 조치를 취해야합니다.




Links