将数组转换为IEnumerable<T>

18

令我惊讶的是,我得到了以下声明:

public static IEnumerable<SomeType> AllEnums 
  => Enum.GetValues(typeof(SomeType));

我抱怨无法将System.Array转换为System.Collection.Generic.IEnumerable。 我以为后者继承了前者。 显然我错了。

由于我无法使用LINQ或.ToList,因此我不确定如何正确地处理它。 我更喜欢避免显式转换,而且由于这是一堆枚举值,我认为as SomeType也不会很有用。


Enum.GetValues 返回的是一个没有强类型的数组。所以这里并不意外。 - Ondrej Tucny
2个回答

23

通用的Array基类没有类型,因此它不实现任何特定于类型的接口;但是,可以直接将向量强制转换 - 而GetValues实际上返回一个向量;所以:

public static IEnumerable<SomeType> AllEnums
    = (SomeType[])Enum.GetValues(typeof(SomeType));

或者可能更简单:

public static SomeType[] AllEnums 
    = (SomeType[])Enum.GetValues(typeof(SomeType));

有没有办法使用数组类型而不是枚举来实现这个? - toughQuestions
@toughQuestions 它应该适用于任何协变数组类型(并非所有数组都是如此)- 你有具体的例子吗? - Marc Gravell
不确定我是否应该将其放在评论部分,但是假设您有一个名为“IEnumerable CheckRange(IEnumerable value)”的方法。该方法需要检查和限制“value”。因此,如果我们将“value”转换为数组,然后修改它,那么我就不能像您建议的那样“获取值”并将其作为IEnumerable返回。谢谢。 - toughQuestions
@toughQuestions你是在寻找.Cast<T>() / .OfType<T>()吗? - Marc Gravell

5
我认为后者是从前者继承而来的。 Enum.GetValues 返回 Array,它实现了非泛型的 IEnumerable,因此您需要添加一个转换:
public static IEnumerable<SomeType> AllEnums = Enum.GetValues(typeof(SomeType))
    .Cast<SomeType>()
    .ToList(); 

这适用于LINQ,因为Cast<T>扩展方法是为非泛型的IEnumerable接口定义的,而不仅适用于IEnumerable<U>

编辑:调用ToList()可以避免与使用延迟执行的LINQ方法生成的IEnumerable<T>多次遍历相关的效率低下。感谢Marc的精彩评论!


1
每当访问时,这将进行装箱和拆箱,请注意。 - Marc Gravell
请注意,您可以直接将 Enum.GetValues 的结果转换为 IEnumerable<SomeType>,无需使用 Cast<> - DavidG

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接