Why Enumerable.Cast raises an InvalidCastException?

22,942

Solution 1

Well, you have incorrect expectations of Cast, that's all - it's meant to deal with boxing/unboxing, reference and identity conversions, and that's all. It's unfortunate that the documentation isn't as clear as it might be :(

The solution is to use Select:

doubleNumbers2 = intNumbers.Select(x => (double) x).ToArray();

Solution 2

To add to Jon's answer cast is mainly useful for objects that implement IEnumerable but nothing else. Take XmlNodeList for example. If you don't have the luxury of using System.Xml.Linq namespace you can use Cast<XmlElement> to write some nice LINQ queries against it.

var result = xmlNodeList
    .Cast<XmlElement>()
    .Select(e=> e.GetAttribute("A") + e.GetAttribute("B"))
    .ToArray();
Share:
22,942
outlookrperson
Author by

outlookrperson

Microsoft .NET (MCT/MCSD/MCPD) Instructor/Consultant established in São Paulo/Brazil Renato Person | MCT, MCSD

Updated on July 09, 2022

Comments

  • outlookrperson
    outlookrperson almost 2 years

    If I can implicitly cast an integer value to a double, like:

    int a = 4;    
    double b = a;
    // now b holds 4.0
    

    Why can I not do this:

    int[] intNumbers = {10, 6, 1, 9};    
    double[] doubleNumbers2 = intNumbers.Cast<double>().ToArray();
    

    I get a "Specified cast is not valid" InvalidCastException exception.

    Doing the opposite (casting from double to int) results in the same error.

    What am I doing wrong?

  • outlookrperson
    outlookrperson about 14 years
    great. It works to me. In fact as you have mentioned, the documentation is not clear about it. The documentation says "Converts the elements of an IEnumerable to the specified type". But reading foward, I realize that the IEnumerable.Cast<> is used to enable the standard query operators to be invoked on non-generic collections. Tks!
  • Jon Skeet
    Jon Skeet about 14 years
    It's also useful pre-C# 4 to get something like covariance: you can convert an IEnumerable<Cat> to an IEnumerable<Animal> via Cast, for instance. This isn't a problem as of C# 4, of course... although you might use Cast to perform the reverse conversion.
  • Pop Catalin
    Pop Catalin about 14 years
    Cast performed value type and user defined conversions prior to Visual Studio 2008 SP1, when this behavior was removed: "Queries over non-generic collections now use standard C# cast semantics. " msdn.microsoft.com/en-us/library/dd310284.aspx
  • Shimmy Weitzhandler
    Shimmy Weitzhandler over 13 years
    What takes more performance, IEnumerable.Cast or Select(x=>(MyClass)x)?
  • Jon Skeet
    Jon Skeet over 13 years
    @Shimmy: I'd have to measure to check - I doubt that it's significant. I'd expect the Cast<> call to be very silghtly faster, but almost unmeasurably so.
  • Shimmy Weitzhandler
    Shimmy Weitzhandler over 13 years
    Thanks @Jon, the question is if the Cast<> is an iterator function or is to be performed on the collection wrapper level (if there is such a thing at all).
  • Jon Skeet
    Jon Skeet over 13 years
    @Shimmy: I don't know what you mean by "collection wrapper level" but Cast is a normal extension method on IEnumerable. In fact, thinking about it, in some cases Select will be faster - if it's a List<int> for example, Cast would have to box and unbox each element, whereas Select won't.
  • Felix K.
    Felix K. about 12 years
    @JonSkeet I've tested the performance recently and select is faster in the most cases ( 1.000.000 runs @ 1000 iterations for both test's ).