如何将枚举转换为C#中的列表?
这个问题在这里已经有了答案:
这将返回Enum的所有值的IEnumerable<SomeEnum>
。
Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>();
如果你希望这是一个List<SomeEnum>
,只需在.Cast<SomeEnum>()
之后添加.ToList()
.Cast<SomeEnum>()
。
要在阵列上使用Cast函数,您需要在使用部分中包含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>()
。 问题在于它使用Array
类的非泛型IEnumerable
实现。 这应该包括将每个值装箱到System.Object
框中,然后使用Cast<>
方法将所有这些值再次取消装箱。 幸运的是.Cast<>
方法似乎在开始迭代集合之前检查其IEnumerable
参数的运行时类型( this
参数),因此它毕竟不是那么糟糕。 事实证明.Cast<>
允许通过相同的数组实例。
如果您遵循.ToArray()
或.ToList()
,如下所示:
Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList() // DON'T do this
你有另一个问题:当你调用GetValues
然后用.ToList()
调用创建一个新的集合( List<>
)时,你创建一个新的集合(数组)。 所以这是整个集合的一个(额外)冗余分配来保存这些值。