协慌网

登录 贡献 社区

如何在 C#中将枚举转换为列表?

有没有一种方法可以将enum转换为包含所有枚举选项的列表?

答案

这将返回一个 Enum 的所有值IEnumerable<SomeEnum>

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

如果您希望将其作为List<SomeEnum> ,只需在.Cast<SomeEnum>() .ToList()即可。

要在数组上使用 Cast 函数,您需要在 using 部分中System.Linq

更简单的方法:

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

简短的答案是,使用:

(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 。但我保证你是SomeEnum[]

每次GetValues时,都必须分配一个新数组并将这些值复制到新数组中。这是因为数组可能会被方法的 “消费者” 写入(修改),因此它们必须创建一个新数组以确保值不变。 .NET 1.0 没有好的只读集合。

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

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

然后,您可以AllSomeEnumValues ,并且可以安全地重用同一集合。

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

许多其他答案使用.Cast<SomeEnum>() 。问题在于它使用ArrayIEnumerable实现。这应该涉及将每个值装箱到System.Object框中,然后使用Cast<>方法再次将所有这些值装箱。幸运的是, .Cast<> IEnumerable参数( this参数)的运行时类型,因此毕竟还不错。事实证明.Cast<>允许相同的数组实例通过。

如果跟随.ToArray().ToList() ,则如下所示:

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

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