tags:

views:

1063

answers:

8

Though I know what boxing and unboxing is. But I can't comprehend the real use of it. Why and where should I use it.

short s=25;
object objshort=s;  //Boxing

short anothershort=(short)objshort; //UnBoxing

Please help. Thanks in advance.

A: 

Boxing and Unboxing are specifically used to treat value-type objects as reference-type; moving their actual value to the managed heap and accessing their value by reference.

Without boxing and unboxing you could never pass value-types by reference; and that means you could not pass value-types as instances of Object.

STW
+33  A: 

Why

To have a unified type system and allow value types to have a completely different representation of their underlying data from the way that reference types represent their underlying data (e.g., an int is just a bucket of thirty-two bits which is completely different than a reference type).

Think of it like this. You have a variable o of type object. And now you have an int and you want to put it into o. o is a reference to something somewhere, and the int is emphatically not a reference to something somewhere (after all, it's just a number). So, what you do is this: you make a new object that can store the int and then you assign a reference to that object to o. We call this process "boxing."

So, if you don't care about having a unified type system (i.e., reference types and value types have very different representations and you don't want a common way to "represent" the two) then you don't need boxing. If you don't care about having int represent their underlying value (i.e., instead have int be reference types too and just store a reference to their underlying value) then you don't need boxing.

where should I use it.

For example, the old collection type ArrayList only eats objects. That is, it only stores references to somethings that live somewhere. Without boxing you can not put an int into such a collection. But with boxing, you can.

Now, in the days of generics you don't really need this and can generally go merrily along without thinking about the issue. But there are a few caveats to be aware of:

This is correct:

double e = 2.718281828459045;
int ee = (int)e;

This is not:

double e = 2.718281828459045;
object o = e; // box
int ee = (int)o; // runtime exception

Instead you must do this:

double e = 2.718281828459045;
object o = e; // box
int ee = (int)(double)o;

First we have to explicitly unbox the double ((double)o) and then cast that to an int.

What is the result of the following:

double e = 2.718281828459045;
double d = e;
object o1 = d;
object o2 = e;
Console.WriteLine(d == e);
Console.WriteLine(o1 == o2);

Think about it for a second before going on to the next sentence.

If you said True and False great! Wait, what? That's because == uses object equality which checks if the references are equal, not if the underlying values are equal. This is a dangerously easy mistake to make. Perhaps even more subtle

double e = 2.718281828459045;
object o1 = e;
object o2 = e;
Console.WriteLine(o1 == o2);

will also print False!

Better to say:

Console.WriteLine(o1.Equals(o2));

which will then, thankfully, print True.

One last subtlety:

[struct|class] Point {
    public int x, y;

    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}

Point p = new Point(1, 1);
object o = p;
p.x = 2;
Console.WriteLine(((Point)o).x);

What is the output? It depends! If Point is a struct then the output is 1 but if Point is a class then the output is 2! A boxing conversion makes a copy of the value being boxed explaining the difference in behavior.

Jason
Thanks a lot .You made it much clear.
vaibhav
very nice explanation, +1.
Idan K
A: 

The last place I had to unbox something was when writing some code that retrieved some data from a database (wasn't using Linq to Sql, just plain old ADO.NET):

int myIntValue = (int)reader["MyIntValue"];

Basically, if you're working with older API's before generics, you'll encounter boxing, other than that, it isn't that common.

BFree
+3  A: 

Boxing isn't really something that you use - it is something the runtime uses so that you can handle reference and value types in the same way when necessary. For example, if you used an ArrayList to hold a list of integers, the integers got boxed to fit in the object-type slots in the ArrayList.

Using generic collections now, this pretty much goes away. If you create a List<int>, there is no boxing done - the List<int> can hold the integers directly.

Ray
You still need boxing for things like composite string formatting. You might not see it as often when using generics, but it's definitely still there.
Jeremy Seghi
true - it shows up all the time in ADO.NET too - sql parameter values are all 'object's no matter what the real data type is
Ray
+7  A: 

Use cases for boxing a value type in C#?

TheJuice
A: 

When a method only takes a reference type as a parameter (say a generic method constrained to be a class via the new constraint), you will not be able to pass a reference type to it and have to box it.

This is also true for any methods that take object as a parameter - this will have to be a reference type.

Oded
+3  A: 

In the .NET framework, there are two species of types--value types and reference types. This is relatively common in OO languages.

One of the important features of object oriented languages is the ability to handle instances in a type-agnostic manner. This is referred to as polymorphism. Since we want to take advantage of polymorphism, but we have two different species of types, there has to be some way to bring them together so we can handle one or the other the same way.

Now, back in the olden days (1.0 of Microsoft.NET), there weren't this newfangled generics hullabaloo. You couldn't write a method that had a single argument that could service a value type and a reference type. That's a violation of polymorphism. So boxing was adopted as a means to coerce a value type into an object.

If this wasn't possible, the framework would be littered with methods and classes whose only purpose was to accept the other species of type. Not only that, but since value types don't truly share a common type ancestor, you'd have to have a different method overload for each value type (bit, byte, int16, int32, etc etc etc).

Boxing prevented this from happening. And that's why the British celebrate Boxing Day.

Will
And that's why the British celebrate Boxing Day. =)
Brett Widmeier
A: 

Move from stack to heap memory

Anirudh
we already knew that.
vaibhav
@vaibhav: Be careful! The above statement isn't entirely true. More importantly, for almost all purposes it's irrelevant.
Jason