为什么IEnumerable的ToArray()扩展方法抛出ArrayTypeMismatchException?

时间:2009-12-14 12:15:59

标签: .net vb.net exception ienumerable

为什么下一个示例会抛出System.ArrayTypeMismatchException?

New Int16(){4,5,6}.Cast(of UInt16).ToArray()

我希望这一行返回一个包含4,5和6的UInt16数组。

提前致谢。

2 个答案:

答案 0 :(得分:7)

这是IMO CastToArray中的错误。这个答案中的代码是在C#中,但希望你能看到它的内容:)

我相信Cast首先会尝试查看简单的引用转换是否有效 - 即它可以返回相同的引用。

例如:

String x = "hello";
IEnumerable<char> y = x.Cast<char>();
Console.WriteLine(object.ReferenceEquals(x, y)); // Prints true

不幸的是,它使用CLR规则来实现兼容性 - UInt16[]Int16[] 兼容。这导致了这种情况发生:

short[] array = new short[]{4, 5, 6};
IEnumerable<ushort> cast = array.Cast<ushort>();
Console.WriteLine(object.ReferenceEquals(array, cast)); // Prints True

不幸的是,如果您尝试拨打ToArray(),那就不开心了:

// Explicit type argument just for clarity
cast.ToArray<ushort>(); // Bang

ToArray无疑会尝试进行一些优化 - 在这种特殊情况下失败,因为类型不是它真正期望的类型。

我认为正确的行为应该是Cast返回一个惰性迭代器,但是当它稍后执行时会失败。例如,如果您尝试从Int16转到Int32,就会发生这种情况。

现在,要回到真正想要做的事情:请改为使用Select来电。 Cast仅适用于拆箱操作和参考类型转换。

答案 1 :(得分:5)

因为Int16UInt16是不同的类型。你可以试试这个:

New Int16() {4, 5, 6}.Select(Function(x) CType(x, UInt16)).ToArray()