26

Maybe I'm crazy, but I thought this was a valid cast:

(new int[]{1,2,3,4,5}).Cast<double>()

Why is LinqPad throwing a

InvalidCastException: Specified cast is not valid.

?

John Saunders
  • 160,644
  • 26
  • 247
  • 397
mpen
  • 272,448
  • 266
  • 850
  • 1,236
  • Also see [why-cant-i-unbox-an-int-as-a-decimal](http://stackoverflow.com/questions/1085097/why-cant-i-unbox-an-int-as-a-decimal). Very closely related.. – nawfal Nov 29 '13 at 18:43

1 Answers1

39

C# allows a conversion from int directly to double, but not from int to object to double.

int i = 1;
object o = i;
double d1 = (double)i; // okay
double d2 = (double)o; // error

The Enumerable.Cast extension method behaves like the latter. It does not convert values to a different type, it asserts that values are already of the expected type and throws an exception if they aren't.

You could try (new int[]{1,2,3,4,5}).Select(i => (double)i) instead to get the value-converting behaviour.

  • Another way to think of it is that the C# cast operator (brackets) does both explicit type coercion (int -> double) and typecasting (checked conversion of references from one type to another compatible reference). But Linq's Cast method just does the latter. – Oliver Bock Mar 29 '16 at 00:57
  • @OliverBock That's a valid way to think of it, but to be honest, I don't think that distinction you're making between naming the two meanings of casts is widely accepted. –  Mar 29 '16 at 05:35
  • Oops! But I'm wondering why it is failing for `value types`. Had it been a case of two `reference type` variables where one of the two types was castable to the other one then this wouldn't have failed. I'm wondering why C# has implemented it this way just for `value types` when every type in CTS inherits from `System.Object`? – RBT Jul 28 '16 at 00:03
  • Interestingly, this code `object obj = 2; double d1 = (double)i; // okay` gives no error. I'm sure here 2 must have been implicitly considered as an integer by the run-time while getting assigned to `obj`. – RBT Jul 28 '16 at 00:08
  • 1
    @RBT `(double)i` might not give an error, but `(double)obj` should. –  Jul 28 '16 at 05:41