【问题标题】:Why won't Cast<double>() work on IEnumerable<int>? [duplicate]为什么 Cast<double>() 不能在 IEnumerable<int> 上工作? [复制]
【发布时间】:2009-12-08 06:36:56
【问题描述】:

可能的重复:
Enumerable.Cast<T> extension method fails to cast from int to long, why ?
Puzzling Enumerable.Cast InvalidCastException
Cast/Convert IEnumerable<T> to IEnumerable<U> ?

我正在尝试将整数数组转换为双精度数组(这样我就可以将它传递给一个接受双精度数组的函数)。

最明显的解决方案(至少对我而言)是对 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<double>().ToArray();
            PrintEnumerable(doubleArrayDoesntWork, "doubleArrayDoesntWork: ");

            // Pause
            Console.ReadLine();
        }

        private static void PrintEnumerable<T>(
            IEnumerable<T> toBePrinted, string msgPrefix)
        {
            Console.WriteLine(
                msgPrefix + string.Join(
                    ",", toBePrinted.Select(x => x.ToString()).ToArray()));
        }
    }

}

【问题讨论】:

标签: c# .net ienumerable type-conversion casting


【解决方案1】:

问题在于强制转换运算符(重载)在编译时被解析。 试着想想 Cast 是如何实现的。我敢打赌代码看起来像这样:

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

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

选择示例:

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

之所以有效,是因为编译器知道这两种类型,并且能够调用适当的重载运算符。

【讨论】:

  • 这里要观察的主要事情可能是类型转换 syntax 用于类型转换 转换运算符。数值类型之间的转换是转换运算符,而不是强制转换。
【解决方案2】:

尝试使用 Array 类的 Convertall 方法。它使您可以显式控制转换。

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

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

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

【讨论】:

  • 这与使用select相同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-28
  • 2012-08-04
  • 1970-01-01
  • 2020-02-03
  • 1970-01-01
  • 2019-12-02
  • 1970-01-01
相关资源
最近更新 更多