为什么Cast ()不能在IEnumerable 上工作?

可能重复:
Enumerable.Cast 扩展方法无法从int转换为long,为什么?
令人费解的Enumerable.Cast InvalidCastException
将IEnumerable 转换为IEnumerable

我正在尝试将整数数组转换为双精度数组(因此我可以将它传递给一个带有双精度数组的函数)。

最明显的解决方案(至少对我而言)是对IEnumerable使用Cast扩展函数,但它给了我一个InvalidCastException,我不明白为什么。 我的解决方法是使用Select,但我认为Cast看起来更整洁。

有人能告诉我为什么Cast方法不起作用?

希望下面的代码说明我的问题:

namespace ConsoleApplication1 { using System; using System.Collections.Generic; using System.Linq; class Program { static void Main() { var intArray = new[] { 1, 2, 3, 4 }; PrintEnumerable(intArray, "intArray: "); var doubleArrayWorks = intArray.Select(x => (double)x).ToArray(); PrintEnumerable(doubleArrayWorks, "doubleArrayWorks: "); // Why does this fail?? var doubleArrayDoesntWork = intArray.Cast().ToArray(); PrintEnumerable(doubleArrayDoesntWork, "doubleArrayDoesntWork: "); // Pause Console.ReadLine(); } private static void PrintEnumerable( IEnumerable toBePrinted, string msgPrefix) { Console.WriteLine( msgPrefix + string.Join( ",", toBePrinted.Select(x => x.ToString()).ToArray())); } } 

}

问题来自于在编译时解析了转换操作符(重载)。 试着想一下Cast是如何实现的。 我打赌代码看起来像这样:

 public static IEnumerable Cast(this IEnumerable source) { foreach(object element in source) { yield return (T)(object)element; } } 

编译器拥有的所有信息都是需要将对象强制转换为类型T.为此,它将使用默认的inheritance强制转换。 不会使用自定义重载运算符。 在您的示例中,int不是double,因此转换将失败。

选择示例:

 source.Select(a => (double)a)); 

因为编译器知道这两种类型并且能够调用适当的重载操作符,所以可以正常工作。

尝试使用Array类的Convertall方法。 它可以让您明确控制转换。

 var doubleArray = Array.ConvertAll(intArray, num => (double)num); 

这会绕过您遇到的内部错误。

其他方法也可以让您明确控制转换过程。