Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange casting behaviour. Cannot cast object (int) to long

Tags:

c#

.net

clr

I have the following code:

int intNumber1 = 100; object intNumber2 = 100; bool areNumberOfTheSameType = intNumber1.GetType() == intNumber2.GetType(); // TRUE bool areEqual = intNumber1.Equals(intNumber2); // TRUE  long longNumber1 = (long) intNumber1; // OK long longNumber2 = (long) intNumber2; // InvalidCastException. Why? 

Why doesn't the second cast work? I realize that it might be because the object doesn’t have an explicit cast to a long, but if we look at its type on runtime it is System.Int32.

If I use var or dynamic instead of object, it works.

Any thoughts?

like image 940
Bashir Magomedov Avatar asked Aug 22 '10 13:08

Bashir Magomedov


People also ask

How do you convert a number to an integer in Haskell?

fromInteger :: Num a => Integer -> a. as well as for converting to Integer s: toInteger:: Integral a => a -> Integer.

Does casting create a new object?

Casting does not create a new object (at least, not unless new conversion operators have been defined, which is uncommon in non-numeric types, and doesn't apply in your example). It merely instructs the compiler how to "treat" an object.

Can you cast in Haskell?

And since Haskell is not object-oriented, there is no inheritance relationship that required any cast. There simply aren't meaningless object values that needed runtime-checking/casting. For expressing alternatives, you'll have to define a union type, a typeclass or use the Either type.


2 Answers

Cast from int to long is interpreted as conversion between the two types.

Cast from object to int is interpreted as unboxing a boxed int.

It is the same syntax, but it says two different things.

In the working cases (intlong, object (boxed int)→int), the compiler knows exactly what code to produce. If boxed intlong was to work, the compiler would have to somehow figure out which conversion to use, but it doesn't have enough information to do it.

See also this blog post from Eric Lippert.

like image 112
svick Avatar answered Sep 21 '22 08:09

svick


The object holds a type int. But it's considered an object (which is a boxed int) and a boxed value type can generally only be cast to its underlying type (the type that is boxed).

To cast it to another type, you first have to cast it to its underlying type. This works:

long longNumber2 = (long) (int) intNumber2; 

The reason that var works is that the compiler infers the type at compile time. That means, when you use var, the type of intNumber2 (if you use typeof) will be int. Whereas when you use object, the type will be object.

Using dynamic is a whole different process and cannot be compared with var. Here, the conversion / casting takes place at runtime, using reflection and the DLR library. It will dynamically find the underlying type, find that it has a conversion operator and uses that.

like image 33
Abel Avatar answered Sep 21 '22 08:09

Abel