43

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?

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
outlookrperson
  • 2,761
  • 7
  • 32
  • 49

2 Answers2

61

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();
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    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! – outlookrperson May 03 '10 at 20:19
  • 1
    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. " http://msdn.microsoft.com/en-us/library/dd310284.aspx – Pop Catalin May 03 '10 at 23:09
  • 1
    What takes more performance, IEnumerable.Cast or Select(x=>(MyClass)x)? – Shimmy Weitzhandler Oct 05 '10 at 04:00
  • @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. – Jon Skeet Oct 05 '10 at 05:54
  • 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). – Shimmy Weitzhandler Oct 05 '10 at 08:49
  • 2
    @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` for example, `Cast` would have to box and unbox each element, whereas `Select` won't. – Jon Skeet Oct 05 '10 at 09:02
  • 1
    @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 ). – Felix K. Mar 20 '12 at 21:54
9

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();
ChaosPandion
  • 77,506
  • 18
  • 119
  • 157
  • 2
    It's also useful pre-C# 4 to get something like covariance: you can convert an `IEnumerable` to an `IEnumerable` 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. – Jon Skeet May 03 '10 at 20:24