patterncsharpCritical
Why do we need boxing and unboxing in C#?
Viewed 0 times
unboxingwhyandboxingneed
Problem
Why do we need boxing and unboxing in C#?
I know what boxing and unboxing is, but I can't comprehend the real use of it. Why and where should I use it?
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; //UnboxingSolution
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
Think of it like this. You have a variable
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
where should I use it.
For example, the old collection type
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:
This is not:
Instead you must do this:
First we have to explicitly unbox the
What is the result of the following:
Think about it for a second before going on to the next sentence.
If you said
will also print
Better to say:
which will then, thankfully, print
One last subtlety:
What is the output? It depends! If
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 cannot 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 exceptionInstead 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 == on reference types uses reference-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 subtledouble 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.Code Snippets
double e = 2.718281828459045;
int ee = (int)e;double e = 2.718281828459045;
object o = e; // box
int ee = (int)o; // runtime exceptiondouble e = 2.718281828459045;
object o = e; // box
int ee = (int)(double)o;double e = 2.718281828459045;
double d = e;
object o1 = d;
object o2 = e;
Console.WriteLine(d == e);
Console.WriteLine(o1 == o2);double e = 2.718281828459045;
object o1 = e;
object o2 = e;
Console.WriteLine(o1 == o2);Context
Stack Overflow Q#2111857, score: 549
Revisions (0)
No revisions yet.