views:

379

answers:

2
+3  Q: 

IEnumerable.Cast<>

If I can implicitly cast an integer value to a double (and vice versa), 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?

+5  A: 

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
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!
Renato Person
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
What takes more performance, IEnumerable.Cast or Select(x=>(MyClass)x)?
Shimmy
@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
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
@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.
Jon Skeet
@Jon excelent point Jon, thanks again.
Shimmy
A: 

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
tks! Interesting example.
Renato Person
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.
Jon Skeet
@Jon - I stand corrected.
ChaosPandion