RJN
RJN

Reputation: 736

Why does unboxing require explicit casting in C#?

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

Answers (7)

Sergey Berezovskiy
Sergey Berezovskiy

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

NicoRiff
NicoRiff

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

Reginald Blue
Reginald Blue

Reputation: 1002

Use of Dynamic avoids the cast

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

MakePeaceGreatAgain
MakePeaceGreatAgain

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

Georg Jung
Georg Jung

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

Alberto Chiesa
Alberto Chiesa

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

Connell.O'Donnell
Connell.O'Donnell

Reputation: 3713

Any int is convertible to an object. Not all objects can be cast to ints.

Upvotes: 4

Related Questions