Reputation: 736
Boxing is the process of converting a value type into a managed heap object, which is implicit. Unboxing is the reverse process, for which the compiler requires an explicit cast. Since boxing stores the data type, why can't unboxing use that instead of asking for an explicit cast?
class BoxUnBox
{
static void Main()
{
int i = 123; // a value type
object o = i; // boxing
int j = (int)o; // unboxing - Why is an explicit cast required?
}
}
Upvotes: 20
Views: 3299
Reputation: 236268
Your question is not related to unboxing operation only. Actually it should sound as "Why should I use explicit conversion?" Consider following example:
int i = 123;
long l = i;
int j = (int)l; // OMG why??
The answer is simple and you can find it in C# specification 6.2 Explicit conversions:
The explicit conversions are conversions that cannot be proven to always succeed, conversions that are known to possibly lose information, and conversions across domains of types sufficiently different to merit explicit notation.
In example above you might lose information, because long
can hold values which do not fit int
range. But you will never lose information when assigning int
to long
:
long l = i; // safe
In your example you need explicit conversion because implicit conversion cannot be proven to always succeed. Variables of object
type can reference
literally any type. What about string?
object o = i; // implicit and always safe
o = "Now I have a machinegun ho-ho-ho"; // safe too
int j = o; // will not succeed if o is string
Analogy
Object variable is like a black box where you can put anything - music CD, pen, phone or banana. Not only you, but anyone can put something there. If the last thing which you put in a black box in the morning was a banana, can you come back in the evening and eat whatever you pull out from the black box? If you live alone, and room is closed, and your memory is excellent, and... then you can. And you will wonder why everybody checks their box's content before eating it. But if you are not live alone, or the room is not closed, or you can forget just once that you have put the phone into the box... Bon appetite
Upvotes: 42
Reputation: 4883
The compiler cannot guarantee what is inside of your object. That is why you need to explicitly cast as the value you expect. For the compiler:
This is as hazardous
object o = 45;
int j = (int)o;
as this:
object o = "something";
int j = (int)o;
And that cannot be allowed at compile time.
Upvotes: 3
Reputation: 1002
Not to take away from anything that has been said, but I wanted to point out that, technically, the cast is not always needed to perform the unboxing. The dynamic keyword allows for the system to perform the unboxing and conversion automagically. I am neither recommending nor discouraging the use of dynamic, merely pointing out it's behavior.
static void DynamicTest()
{
int i = 123; // a value type
object o = i; // boxing
dynamic d = o; // shift to dynamic
int j = d; // unboxing - No cast required
}
Edit: Jeroen Mostert wisely points out that the dynamic keyword is not any kind of magic that always makes this work. It merely defers evaluation to a runtime behavior. So, while the above example will always work, more complex examples will definitely fail. Therefore, one must take care when using the dynamic keyword and expect (try/catch) runtime failures. The dynamic keyword can, none-the-less be a very powerful tool, if used judiciously.
Upvotes: 1
Reputation: 37050
What if someone changes the content of o
to say "Hello World"
. To be sure you know what you're doing, the compiler requires you to explicitly cast the boxed value.
Basically an implicit conversion implies that any instance o
, of type object, can also be represented as an instance of int
which clearly isn't the case. Consider for example this:
int i = -1;
long j = i;
It is clear that your variable i
, which is an integer, can also be considered as long
. This is why implicit casting is accurate here. On the other side, not every long
is also convertable to int
without any loss of data. Thus you need an explicit cast to determine: I know there might be some loss of data, however I don't care about it.
Upvotes: 6
Reputation: 1167
Casting might fail at runtime, depending on what your object
really contains. When implicit unboxing would be possible, you might overlook errors as you may have written something which was meant differently (either by you or you misunderstood someone else's code). The compiler requires you to cast explicitly because you should really want that cast. Otherwise you might mistakenly mix types, which produces verry error prone code. By beeing forced to cast explicitly you are forced to think twice if what you do is right.
Upvotes: 2
Reputation: 7350
Because an Int32
is an Object
, but an Object
may be an Int32
.
The compiler knows what to do in the first case, but you have to tell the compiler you know what you're doing in the second case, and guarantee that the unboxing can be performed.
The inheritance relationship is directional! Parent is different from child.
Upvotes: 5
Reputation: 3713
Any int is convertible to an object. Not all objects can be cast to ints.
Upvotes: 4