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
「しかし、GetValuesがGetNamesが名前を返すのと同じ順序で値を返すことを確認できますか?」-これは非常に良い点であり、まだ対処していません。私はあなたの最初の解決策がおそらく値と文字列を確実に一致させる方法を提供すると思います
TK

こんにちは、これを行っているときにこの「インデックスの不一致」が発生しているという疑いについて言及したことがあります。しかし、これが本当に心配かどうかはまだわかりません。この仮定がうまくいかない可能性がある決定的なケースはありますか?どうも!
Funka

値の不一致をトラブルシューティングする場合Enum.GetName(typeof(MyEnum), val), (int)val)は、出力に列挙型の名前と番号が示されるので、2番目の「val」をintにキャストすることをお勧めします。
グレッグ

GetValuesとGetNamesは同じ順序で戻ります。つまり、「戻り値の配列の要素は、列挙された定数のバイナリ値で(つまり、符号なしの大きさで)ソートされます。」
Russell Borogove 2016年

私はあなたにも呼び出すことによって直接LINQを使用することができると信じてCast<T>結果に:Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>()...
jocull

33

あなたは、配列をキャストする必要があります-返される配列は、要求のタイプ、すなわちで実際にmyEnum[]あなたが頼めばtypeof(myEnum)

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

その後values[0]など


9

その配列をさまざまなタイプの配列にキャストできます。

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 2018

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、2010

3

foreachループの使用についてはどうでしょうか?

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

おそらくそのようなものですか?


私はそれを学びました...しかし、私は「同期」で名前と値の両方にアクセスする必要があります... names [2]はvalues [2]とペアになっていると言い、これをどのように達成するのかわかりませんforeachループ!
TK。

例を追加しました-それが役立つかどうかを確認してください。
TWith2Sugars 2009年

3

古い質問ですが、LINQを使用した少しクリーンなアプローチ .Cast<>()

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

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


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指定子は、enumを文字列としてフォーマットします。Flags属性が列挙型に適用されている場合、結合された値もサポートされます。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.