关于.NET:如何在C中将枚举转换为列表?enum to a list

How do I convert an enum to a list in C#?

本问题已经有最佳答案,请猛点这里访问。

是否有方法将enum转换为包含枚举所有选项的列表?


这将返回枚举所有值的IEnumerable

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

如果你想成为一个List,只需在.Cast()后面加上.ToList()

要在数组上使用cast函数,您需要在使用部分中包含System.Linq


更简单的方法:

1
2
3
4
Enum.GetValues(typeof(SomeEnum))
    .Cast<SomeEnum>()
    .Select(v => v.ToString())
    .ToList();


简短的回答是,使用:

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

如果您需要一个局部变量,它是var allSomeEnumValues = (SomeEnum[])Enum.GetValues(typeof(SomeEnum));

为什么语法是这样的?!

static方法GetValues是在旧的.NET 1.0天内引入的。它返回运行时类型为SomeEnum[]的一维数组。但是,由于它是一个非泛型方法(直到.NET 2.0才引入泛型),因此它不能这样声明其返回类型(编译时返回类型)。

.NET数组确实有一种协方差,但由于SomeEnum将是值类型,并且由于数组类型协方差不适用于值类型,因此它们甚至无法将返回类型声明为object[]Enum[]。(这与.NET 1.0中的GetCustomAttributes重载不同,后者具有编译时返回类型object[],但实际上返回类型SomeAttribute[]的数组,其中SomeAttribute必须是引用类型。)

因此,.NET 1.0方法必须声明其返回类型为System.Array。但我向你保证,这是一辆江户车。

每次使用相同的枚举类型再次调用GetValues时,它都必须分配一个新数组并将值复制到新数组中。这是因为数组可能被方法的"使用者"写入(修改),所以它们必须生成一个新的数组以确保值不变。.NET 1.0没有良好的只读集合。

如果需要多个不同位置的所有值的列表,请考虑只调用一次GetValues,并将结果缓存到只读包装器中,例如:

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

然后您可以多次使用AllSomeEnumValues,并且可以安全地重用相同的集合。

为什么使用.Cast()不好?

许多其他答案都使用.Cast()。问题在于,它使用了Array类的非泛型IEnumerable实现。这应该包括将每个值装箱到一个System.Object框中,然后使用Cast<>方法再次取消装箱所有这些值。幸运的是,.Cast<>方法似乎在开始迭代集合之前检查了它的IEnumerable参数(this参数)的运行时类型,所以它并没有那么糟糕。事实证明,.Cast<>允许同一个数组实例通过。

如果您使用.ToArray().ToList(),如:

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

还有一个问题:当调用GetValues时创建一个新集合(数组),然后使用.ToList()调用创建一个新集合(List<>)。所以这是整个集合的一个(额外的)冗余分配,用于保存值。


以下是我喜欢的方式,使用LINQ:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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();
}

希望它有帮助


1
List <SomeEnum> theList = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList();


非常简单的答案

这是我在一个应用程序中使用的属性

1
2
3
4
5
6
7
public List<string> OperationModes
{
    get
    {
       return Enum.GetNames(typeof(SomeENUM)).ToList();
    }
}


1
Language[] result = (Language[])Enum.GetValues(typeof(Language))

我经常得到这样一个enum值列表:

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


为了有用…用于将值转换为列表的代码,该列表将枚举转换为文本的可读形式。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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();
    }
  }

…及配套系统。字符串扩展方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/// <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();
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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;
}

将枚举转换为列表此处提供的详细信息。


1
2
3
4
5
6
7
8
9
10
11
12
13
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;
}

在顶层代码中,日志是枚举,simplelogtype是日志的结构。

1
2
3
4
5
6
7
public enum Log
{
  None = 0,
  Info = 1,
  Warning = 8,
  Error = 3
}


如果您希望枚举int作为键,名称作为值,那么如果您将数字存储到数据库中,并且它来自枚举,那么这就很好了!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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
2
3
4
5
6
7
8
/// <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
2
3
4
5
6
7
8
9
10
11
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();
}