views:

341

answers:

3

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

}

+3  A: 

Ooops... I didn't check Stack overflow carefully enough before asking. I found my question has already been asked and answered:

http://stackoverflow.com/questions/1684448/enumerable-castt-extension-method-fails-to-cast-from-int-to-long-why

dominic
+2  A: 

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.

John K
That's the same as using select.
Dykam
+2  A: 

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)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 you 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.

AZ