如何使用 IEnumerable.Cast<> 和 .ToArray() 将 int 数组转换为枚举数组?

How to use IEnumerable.Cast<> and .ToArray() to convert int array to an enum array?

考虑以下枚举声明和 int 数组:

enum Test { None };

int[] data = {0};

要将这个 int[] 数组转换为 Test[] 数组,我们可以简单地这样做:

Test[] result = Array.ConvertAll(data, element => (Test)element);

我最初尝试这样做:

Test[] result = data.Cast<Test>().ToArray();

但是,这会在运行时引发异常:

System.ArrayTypeMismatchException: Source array type cannot be assigned to destination array type.

问题一

有没有办法使用 Linq 和 Cast<> 不出错地执行此操作,或者我必须只使用 Array.Convert()

第二题(第一题答对后补充)

为什么它不起作用?

这似乎是一个实现细节转义的情况......考虑:

这会导致错误:

var result = data.Cast<Test>().ToList(); // Happens with "ToList()" too.

但这不是:

var result = new List<Test>();

foreach (var item in data.Cast<Test>())
    result.Add(item);

这也不行:

var result = data.Select(x => x).Cast<Test>().ToList();

明确的含义是在 .ToList() 实现中进行了某种优化,导致了此异常。


附录:

这也有效:

List<int> data = new List<int>{0};
var result = data.Cast<Test>().ToList();

List<int> data = new List<int>{0};
var result = data.Cast<Test>().ToArray();

只有当原始数据是数组时才不行

您可以使用 .Select(e => (Test)e).

在这种情况下不起作用,因为 Cast 首先执行以下检查:

public static IEnumerable<TResult> Cast<TResult>(this IEnumerable source)
{
  IEnumerable<TResult> results = source as IEnumerable<TResult>;
  if (results != null)
    return results;
  // ... the rest of the method
}

事实证明,对于 int[],此检查成功(因此 int[] 因为 IEnumerable<Test> 不为空)。结果,Cast 实际上什么都不做,returns 数组原样。然后,当您调用 ToArray 时,将调用 Array.Copy。它尝试从 int[] 数组复制到 Test[] 数组,但由于类型不匹配而失败。这个异常你看。

因为cast其实什么都没做因为它认为集合已经是desire类型

    IEnumerable<Test> cast = data.Cast<Test>();
    IEnumerable<Test> select = data.Select(e => (Test) e);

    Console.WriteLine(cast == (IEnumerable<int>) data); //True
    Console.WriteLine(select == (IEnumerable<int>) data); //False
    Console.WriteLine(select == cast); //Flase

如您所见,转换 IEnumerable 实际上只是原始数组。因此 .ToArray 正在尝试做类似于 (Test[]) data.ToArray();

的事情