如何使用 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();
的事情
考虑以下枚举声明和 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();