web-dev-qa-db-ja.com

C#で列挙型をリストに変換する方法を教えてください。

enumをすべてのenumのオプションを含むリストに変換する方法はありますか?

541
newWeb

これはEnumのすべての値のIEnumerable<SomeEnum>を返します。

Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();

それをList<SomeEnum>にしたい場合は、.ToList()の後に.Cast<SomeEnum>()を追加するだけです。

ArrayでCast関数を使用するには、usingセクションにSystem.Linqを含める必要があります。

922
Jake Pearson

はるかに簡単な方法:

Enum.GetValues(typeof(SomeEnum))
    .Cast<SomeEnum>()
    .Select(v => v.ToString())
    .ToList();
90
Gili

簡単な答えは、次を使用することです:

(SomeEnum[])Enum.GetValues(typeof(SomeEnum))

ローカル変数に必要な場合は、var allSomeEnumValues = (SomeEnum[])Enum.GetValues(typeof(SomeEnum));です。

なぜこのような構文ですか?!

staticメソッド GetValues は、以前の.NET 1.0で導入されました。ランタイム型SomeEnum[]の1次元配列を返します。しかし、それは非ジェネリックメソッドであるため(ジェネリックは.NET 2.0まで導入されていなかったため)、その戻り値の型(コンパイル時の戻り値の型)を宣言できません。

.NET配列には共分散がありますが、SomeEnumvalue typeになるため、配列型の共分散は値型では機能しないため、戻り型をobject[]またはEnum[]として宣言することさえできませんでした。 (これは、たとえば 。NET 1.0GetCustomAttributesのオーバーロードとは異なります。このオーバーロードは、コンパイル時の戻り型object[]を持ちますが、実際にはSomeAttribute[]型の配列を返します。ここでSomeAttribute必ず参照型です。)

このため、.NET 1.0メソッドは戻り型をSystem.Arrayとして宣言する必要がありました。ただし、SomeEnum[]であることを保証します。

同じ列挙型でGetValuesを再度呼び出すたびに、新しい配列を割り当て、新しい配列に値をコピーする必要があります。これは、配列がメソッドの「コンシューマ」によって書き込まれる(変更される)可能性があるため、値が変更されていないことを確認するために新しい配列を作成する必要があるためです。 .NET 1.0には適切な読み取り専用コレクションがありませんでした。

多くの異なる場所ですべての値のリストが必要な場合は、GetValuesを1回だけ呼び出して、結果を読み取り専用ラッパーにキャッシュすることを検討してください。次に例を示します。

public static readonly ReadOnlyCollection<SomeEnum> AllSomeEnumValues
    = Array.AsReadOnly((SomeEnum[])Enum.GetValues(typeof(SomeEnum)));

その後、AllSomeEnumValuesを何度も使用でき、同じコレクションを安全に再利用できます。

.Cast<SomeEnum>()?を使用するのがなぜ悪いのか

他の多くの回答では、.Cast<SomeEnum>()を使用しています。これの問題は、IEnumerableクラスの非ジェネリックArray実装を使用することです。このshouldには、各値をSystem.Objectボックスにボックス化し、Cast<>メソッドを使用してそれらの値をすべてボックス化解除する必要があります。幸いなことに、.Cast<>メソッドは、IEnumerableパラメーター(thisパラメーター)の実行時型をチェックしてからコレクションの繰り返しを開始するようであるため、それほど悪くはありません。 .Cast<>は同じ配列インスタンスを通過させます。

次のように.ToArray()または.ToList()を使用する場合:

Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList() // DON'T do this

別の問題があります:GetValuesを呼び出すときに新しいコレクション(配列)を作成し、.ToList()呼び出しで新しいコレクション(List<>)を作成します。つまり、値を保持するためのコレクション全体の(余分な)冗長割り当ての1つです。

76

これが私の好きなやり方です、LINQを使って:

public class EnumModel
{
    public int Value { get; set; }
    public string Name { get; set; }
}

public enum MyEnum
{
    Name1=1,
    Name2=2,
    Name3=3
}

public class Test
{
    List<EnumModel> enums = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Select(c => new EnumModel() { Value = (int)c, Name = c.ToString() }).ToList();
}

それが役に立てば幸い

26
Booster2ooo
List <SomeEnum> theList = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList();
20
luisetxenike

非常に単純な答え

これは私が私のアプリケーションの一つで使うプロパティです。

public List<string> OperationModes
{
    get
    {
       return Enum.GetNames(typeof(SomeENUM)).ToList();
    }
}
10
Tyler
Language[] result = (Language[])Enum.GetValues(typeof(Language))
5

私はいつもenumの値のリストをこのようにして得ていました:

Array list = Enum.GetValues(typeof (SomeEnum));
5

有用性のためにここに...値をリストに入れるためのいくつかのコード、それはテキストのために読める形式にenumを変換します

public class KeyValuePair
  {
    public string Key { get; set; }

    public string Name { get; set; }

    public int Value { get; set; }

    public static List<KeyValuePair> ListFrom<T>()
    {
      var array = (T[])(Enum.GetValues(typeof(T)).Cast<T>());
      return array
        .Select(a => new KeyValuePair
          {
            Key = a.ToString(),
            Name = a.ToString().SplitCapitalizedWords(),
            Value = Convert.ToInt32(a)
          })
          .OrderBy(kvp => kvp.Name)
         .ToList();
    }
  }

..とそれをサポートするSystem.String拡張メソッド

/// <summary>
/// Split a string on each occurrence of a capital (assumed to be a Word)
/// e.g. MyBigToe returns "My Big Toe"
/// </summary>
public static string SplitCapitalizedWords(this string source)
{
  if (String.IsNullOrEmpty(source)) return String.Empty;
  var newText = new StringBuilder(source.Length * 2);
  newText.Append(source[0]);
  for (int i = 1; i < source.Length; i++)
  {
    if (char.IsUpper(source[i]))
      newText.Append(' ');
    newText.Append(source[i]);
  }
  return newText.ToString();
}
5
public class NameValue
{
    public string Name { get; set; }
    public object Value { get; set; }
}

public class NameValue
{
    public string Name { get; set; }
    public object Value { get; set; }
}

public static List<NameValue> EnumToList<T>()
{
    var array = (T[])(Enum.GetValues(typeof(T)).Cast<T>()); 
    var array2 = Enum.GetNames(typeof(T)).ToArray<string>(); 
    List<NameValue> lst = null;
    for (int i = 0; i < array.Length; i++)
    {
        if (lst == null)
            lst = new List<NameValue>();
        string name = array2[i];
        T value = array[i];
        lst.Add(new NameValue { Name = name, Value = value });
    }
    return lst;
}

Enumをリストに変換する詳細については ここ をご覧ください。

4
Kiarash
/// <summary>
/// Method return a read-only collection of the names of the constants in specified enum
/// </summary>
/// <returns></returns>
public static ReadOnlyCollection<string> GetNames()
{
    return Enum.GetNames(typeof(T)).Cast<string>().ToList().AsReadOnly();   
}

_ t _ は列挙型の1つです。これを追加:

using System.Collections.ObjectModel; 
1
frigate
private List<SimpleLogType> GetLogType()
{
  List<SimpleLogType> logList = new List<SimpleLogType>();
  SimpleLogType internalLogType;
  foreach (var logtype in Enum.GetValues(typeof(Log)))
  {
    internalLogType = new SimpleLogType();
    internalLogType.Id = (int) (Log) Enum.Parse(typeof (Log), logtype.ToString(), true);
    internalLogType.Name = (Log)Enum.Parse(typeof(Log), logtype.ToString(), true);
    logList.Add(internalLogType);
  }
  return logList;
}

上のコードでは、LogはEnumで、SimpleLogTypeはログの構造です。

public enum Log
{
  None = 0,
  Info = 1,
  Warning = 8,
  Error = 3
}
1

Enum intをキーとして、nameを値として使用する場合は、データベースに番号を保存し、それがEnumからのものであると便利です。

void Main()
{
     ICollection<EnumValueDto> list = EnumValueDto.ConvertEnumToList<SearchDataType>();

     foreach (var element in list)
     {
        Console.WriteLine(string.Format("Key: {0}; Value: {1}", element.Key, element.Value));
     }

     /* OUTPUT:
        Key: 1; Value: Boolean
        Key: 2; Value: DateTime
        Key: 3; Value: Numeric         
     */
}

public class EnumValueDto
{
    public int Key { get; set; }

    public string Value { get; set; }

    public static ICollection<EnumValueDto> ConvertEnumToList<T>() where T : struct, IConvertible
    {
        if (!typeof(T).IsEnum)
        {
            throw new Exception("Type given T must be an Enum");
        }

        var result = Enum.GetValues(typeof(T))
                         .Cast<T>()
                         .Select(x =>  new EnumValueDto { Key = Convert.ToInt32(x), 
                                       Value = x.ToString(new CultureInfo("en")) })
                         .ToList()
                         .AsReadOnly();

        return result;
    }
}

public enum SearchDataType
{
    Boolean = 1,
    DateTime,
    Numeric
}
1
xajler

次のような一般的な方法があります。

public static List<T> GetItemsList<T>(this int enums) where T : struct, IConvertible
{
    if (!typeof (T).IsEnum)
    {
        throw new Exception("Type given must be an Enum");
    }

    return (from int item in Enum.GetValues(typeof (T))
            where (enums & item) == item
            select (T) Enum.Parse(typeof (T), item.ToString(new CultureInfo("en")))).ToList();
}
0
Vitall