开发者

Why won't Cast<double>() work on IEnumerable<int>? [duplicate]

This question already has answers here: Closed 13 years ago.

Possible Duplicates:

Enumerable.Cast<T> extension method fails to cast from int to long, why ?

Puzzling Enumerable.Cast InvalidCastException

Cast/Convert IEnumerable<T> to IEnumerable<U> ?

I'm trying to convert an array of integers to an array of doubles (so I can pass it to a function that takes an array of doubles).

The most obvious solution (to me, at least) is to use the Cast extension function for IEnumerable, but it gives me an InvalidCastException, and I don't understand why. My workaround is to use Select instead, but I think Cast looks neater.

Could someone tell me why the Cast method isn't working?

Hopefully the code below illustrates my problem:

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()));
        }
    }

}


The problem comes from the fact that cast operators (overloaded) are resolved at compile time. Try to think how Cast is implemented. I bet the code looks like this:

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

All the info the compiler has is that it needs to cast an object to a type T. And for that it will use the default inheritance casting. No custom overloaded operator will be used. And in your example an int is not a double so the cast will fail.

The select example:

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

works because the compiler knows both types and it's able to call the appropriate overloaded operator.


Try using the Convertall method of the Array class. It gives you explicit control over the conversion.

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

This bypasses the internal error that you are experiencing.

Other methods give you explicit control over the conversion process too.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜