열거 형을 통해 C # 반복? (System.Array 인덱싱)


113

다음 코드가 있습니다.

// Obtain the string names of all the elements within myEnum 
String[] names = Enum.GetNames( typeof( myEnum ) );

// Obtain the values of all the elements within myEnum 
Array values = Enum.GetValues( typeof( myEnum ) );

// Print the names and values to file
for ( int i = 0; i < names.Length; i++ )
{
    print( names[i], values[i] ); 
}

그러나 값을 인덱싱 할 수 없습니다. 이 작업을 수행하는 더 쉬운 방법이 있습니까?

아니면 완전히 놓친 것이 있습니까!

답변:


204
Array values = Enum.GetValues(typeof(myEnum));

foreach( MyEnum val in values )
{
   Console.WriteLine (String.Format("{0}: {1}", Enum.GetName(typeof(MyEnum), val), val));
}

또는 반환되는 System.Array를 캐스팅 할 수 있습니다.

string[] names = Enum.GetNames(typeof(MyEnum));
MyEnum[] values = (MyEnum[])Enum.GetValues(typeof(MyEnum));

for( int i = 0; i < names.Length; i++ )
{
    print(names[i], values[i]);
}

그러나 GetNames가 이름을 반환하는 것과 동일한 순서로 GetValues가 값을 반환하는지 확인할 수 있습니까?


3
"하지만 GetNames가 이름을 반환하는 것과 동일한 순서로 GetValues가 값을 반환하는지 확인할 수 있습니까?" -이것은 아주 좋은 점이며 아직 다루지 않은 것입니다! 나는 첫 번째 솔루션은 아마 신뢰성 값과 문자열과 일치하는 방법을 제공하는 것이라고 생각
TK합니다.

안녕하세요,이 작업을 수행 할 때 발생하는 "인덱스 불일치"의 의심에 대해 언급 한 적이 있습니다. 그러나 나는 이것이 정말로 관심사인지 아닌지 아직 발견하지 못했습니다. 이 가정이 잘못 될 수있는 확실한 경우가 있습니까? 고마워!
Funka

Enum.GetName(typeof(MyEnum), val), (int)val)출력이 열거 형 이름과 번호를 제공하는 것과 같은 값 불일치를 해결하려면 두 번째 "val"을 int로 캐스팅 할 수 있습니다.
그렉

GetValues ​​및 GetNames는 동일한 순서로 반환됩니다. 즉, "반환 값 배열의 요소는 열거 된 상수의 이진 값 (즉, 부호없는 크기)에 따라 정렬됩니다."
Russell Borogove

Cast<T>결과 를 호출하여 LINQ를 직접 사용할 수도 있습니다.Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()...
jocull

33

배열을 캐스팅해야합니다. 반환 된 배열은 실제로 요청 된 유형입니다. 즉 myEnum[], 다음을 요청하는 경우 typeof(myEnum):

myEnum[] values = (myEnum[]) Enum.GetValues(typeof(myEnum));

그때 values[0]


9

해당 Array를 다른 유형의 Array로 캐스팅 할 수 있습니다.

myEnum[] values = (myEnum[])Enum.GetValues(typeof(myEnum));

또는 정수 값을 원하는 경우 :

int[] values = (int[])Enum.GetValues(typeof(myEnum));

물론 캐스트 된 배열을 반복 할 수 있습니다. :)


7

사전 목록은 어떻습니까?

Dictionary<string, int> list = new Dictionary<string, int>();
foreach( var item in Enum.GetNames(typeof(MyEnum)) )
{
    list.Add(item, (int)Enum.Parse(typeof(MyEnum), item));
}

물론 사전 값 유형을 열거 형 값으로 변경할 수 있습니다.


나는 이것이 갈 길이라고 생각하지만, 불행히도 열거 형은 내가 제어 할 수없는 코드 영역에 있습니다!
TK.

1
실제 정수 열거 형 값을 얻는 유일한 솔루션!
SharpC

5

흥미로운 가능성이있는 또 다른 솔루션 :

enum Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }

static class Helpers
{
public static IEnumerable<Days> AllDays(Days First)
{
  if (First == Days.Monday)
  {
     yield return Days.Monday;
     yield return Days.Tuesday;
     yield return Days.Wednesday;
     yield return Days.Thursday;
     yield return Days.Friday;
     yield return Days.Saturday;
     yield return Days.Sunday;
  } 

  if (First == Days.Saturday)
  {
     yield return Days.Saturday;
     yield return Days.Sunday;
     yield return Days.Monday;
     yield return Days.Tuesday;
     yield return Days.Wednesday;
     yield return Days.Thursday;
     yield return Days.Friday;
  } 
}

4

여기 또 하나가 있습니다. EnumValues에 친숙한 이름을 제공해야했습니다. System.ComponentModel.DescriptionAttribute를 사용하여 각 열거 형 값에 대한 사용자 지정 문자열 값을 표시했습니다.

public static class StaticClass
{
    public static string GetEnumDescription(Enum currentEnum)
    {
        string description = String.Empty;
        DescriptionAttribute da;

        FieldInfo fi = currentEnum.GetType().
                    GetField(currentEnum.ToString());
        da = (DescriptionAttribute)Attribute.GetCustomAttribute(fi,
                    typeof(DescriptionAttribute));
        if (da != null)
            description = da.Description;
        else
            description = currentEnum.ToString();

        return description;
    }

    public static List<string> GetEnumFormattedNames<TEnum>()
    {
        var enumType = typeof(TEnum);
        if (enumType == typeof(Enum))
            throw new ArgumentException("typeof(TEnum) == System.Enum", "TEnum");

        if (!(enumType.IsEnum))
            throw new ArgumentException(String.Format("typeof({0}).IsEnum == false", enumType), "TEnum");

        List<string> formattedNames = new List<string>();
        var list = Enum.GetValues(enumType).OfType<TEnum>().ToList<TEnum>();

        foreach (TEnum item in list)
        {
            formattedNames.Add(GetEnumDescription(item as Enum));
        }

        return formattedNames;
    }
}

사용

 public enum TestEnum
 { 
        [Description("Something 1")]
        Dr = 0,
        [Description("Something 2")]
        Mr = 1
 }



    static void Main(string[] args)
    {

        var vals = StaticClass.GetEnumFormattedNames<TestEnum>();
    }

그러면 "Something 1", "Something 2"가 반환됩니다.


1
설명이 정적 인 경우에만 좋습니다. 설명을 인스턴스 기반으로 변경해야하는 경우이 접근 방식은 작동하지 않습니다.
Llyle

3

foreach 루프를 사용하는 것은 어떻습니까?

  int i = 0;
  foreach (var o in values)
  {
    print(names[i], o);
    i++;
  }

아마도 그런 것입니까?


나는 그것을 알고 ...하지만 '동기화'에서 이름과 값 모두에 액세스해야합니다 ... 이름 [2]이 값 [2]과 짝을 이루고 있다고 말하고 이것을 달성하는 방법이 확실하지 않습니다 foreach 루프!
TK.

예를 추가했습니다. 도움이되는지 확인하세요.
TWith2Sugars

3

오래된 질문이지만 LINQ를 사용하는 약간 더 깨끗한 접근 방식 .Cast<>()

var values = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>();

foreach(var val in values)
{
    Console.WriteLine("Member: {0}",val.ToString());     
}

2

Array에는 지정된 인덱스에서 값을 검색하는 데 사용할 수있는 GetValue (Int32) 메서드가 있습니다.

Array.GetValue


2

형식 문자열을 사용하여이를 단순화 할 수 있습니다. 사용 메시지에 다음 스 니펫을 사용합니다.

writer.WriteLine("Exit codes are a combination of the following:");
foreach (ExitCodes value in Enum.GetValues(typeof(ExitCodes)))
{
    writer.WriteLine("   {0,4:D}: {0:G}", value);
}

D 형식 지정자는 열거 형 값을 10 진수로 형식화합니다. 16 진수 출력을 제공하는 X 지정자도 있습니다.

G 지정자는 열거 형을 문자열로 형식화합니다. 플래그 속성이 열거 형에 적용되면 결합 된 값도 지원됩니다. Flags가 항상 존재하는 것처럼 작동하는 F 지정자가 있습니다.

Enum.Format ()을 참조하십시오.


2

Enum.GetValues ​​결과에서 int로 캐스팅하면 숫자 값이 생성됩니다. ToString ()을 사용하면 친숙한 이름이 생성됩니다. Enum.GetName에 대한 다른 호출은 필요하지 않습니다.

public enum MyEnum
{
    FirstWord,
    SecondWord,
    Another = 5
};

// later in some method  

 StringBuilder sb = new StringBuilder();
 foreach (var val in Enum.GetValues(typeof(MyEnum))) {
   int numberValue = (int)val;
   string friendyName = val.ToString();
   sb.Append("Enum number " + numberValue + " has the name " + friendyName + "\n");
 }
 File.WriteAllText(@"C:\temp\myfile.txt", sb.ToString());

 // Produces the output file contents:
 /*
 Enum number 0 has the name FirstWord
 Enum number 1 has the name SecondWord
 Enum number 5 has the name Another
 */

0

사용자 정의 Enum 객체를 반복하는 간단한 방법은 다음과 같습니다.

For Each enumValue As Integer In [Enum].GetValues(GetType(MyEnum))

     Print([Enum].GetName(GetType(MyEnum), enumValue).ToString)

Next

1
OP가 C #을 요청했다고 생각합니다.
jm.

0

고대의 질문이지만 3Dave의 대답은 가장 쉬운 접근 방식을 제공했습니다. 디버깅을 위해 데이터베이스의 열거 형 값을 디코딩하기 위해 Sql 스크립트를 생성하는 작은 도우미 메서드가 필요했습니다. 훌륭하게 작동했습니다.

    public static string EnumToCheater<T>() {
        var sql = "";
        foreach (var enumValue in Enum.GetValues(typeof(T)))
            sql += $@"when {(int) enumValue} then '{enumValue}' ";
        return $@"case ?? {sql}else '??' end,";
    }

정적 메서드에 있으므로 사용법은 다음과 같습니다.

var cheater = MyStaticClass.EnumToCheater<MyEnum>()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.