值类型的装箱、拆箱
值类型是一种比引用类型更加轻型的一种类型,要将值类型转为引用类型需要装箱, 装箱在.NET发生以下操作:
- 要计算值类型每个字段的所需内存量,同时因为要转换为引用类型必定要加上同步块索引和对象指针所占用的内存,再根据大小来申请内存
- 申请好之后当然是将所有的值赋值到托管堆中
- 最后返回对象的用
与其意义上相反的操作就是拆箱:将引用类型转为值类型。其中要说明的是,拆箱操作要付出的代价要比装箱却要小的多,主要为
- 获取对象个属性的地址
- 将对象值复制到栈中。
本质上是获取引用类型的指针。
实例说明
- 下面来一个小例子:
View Code
1
static
void Main(
string[] args)
2 {
3 First();
4 Second();
5 }
6 static void First()
7 {
8 Int32 a = 1;
9 object v = a;
10 a = 123;
11 Console.WriteLine(a + " , " + v);
12 }
13 static void Second()
14 {
15 Int32 a = 1;
16 object v = a;
17 a = 123;
18 Console.WriteLine(a.ToString() + " , " + v.ToString());
19
2 {
3 First();
4 Second();
5 }
6 static void First()
7 {
8 Int32 a = 1;
9 object v = a;
10 a = 123;
11 Console.WriteLine(a + " , " + v);
12 }
13 static void Second()
14 {
15 Int32 a = 1;
16 object v = a;
17 a = 123;
18 Console.WriteLine(a.ToString() + " , " + v.ToString());
19
方法First和方法Second各自装箱了几次?答案为:3和1.因为 a + "," + v会调用String.Concat(Object arg[]),在First里就会发生2次装箱,而ToString返回String类型避免了装箱
- 例子:
struct Point : IComparable
{
private Int32 x, y;
public Point(Int32 _x, Int32 _y)
{
x = _x;
y = _y;
}
public override string ToString()
{
return string.Format( " {0},{1} ", x, y);
}
public Int32 CompareTo(Point p)
{
return Math.Sign( this.x * this.x + this.y * this.y - p.x * p.x - p.y * p.y);
}
public Int32 CompareTo( object o)
{
if ( this.GetType() != o.GetType())
throw new ArgumentException( " o is not point ");
else
return CompareTo((Point)o);
}
}
class Program
{
static void Main( string[] args)
{
Point p1 = new Point( 10, 10);
Point p2 = new Point( 20, 20);
Console.WriteLine(p1.ToString());
Console.WriteLine(p1.GetType());
Console.WriteLine(p1.CompareTo(p2));
IComparable compare = p1;
Console.WriteLine(compare.GetType());
Console.WriteLine(p1.CompareTo(compare));
p2 = (Point)compare;
Console.WriteLine(p2.ToString());
}
}
{
private Int32 x, y;
public Point(Int32 _x, Int32 _y)
{
x = _x;
y = _y;
}
public override string ToString()
{
return string.Format( " {0},{1} ", x, y);
}
public Int32 CompareTo(Point p)
{
return Math.Sign( this.x * this.x + this.y * this.y - p.x * p.x - p.y * p.y);
}
public Int32 CompareTo( object o)
{
if ( this.GetType() != o.GetType())
throw new ArgumentException( " o is not point ");
else
return CompareTo((Point)o);
}
}
class Program
{
static void Main( string[] args)
{
Point p1 = new Point( 10, 10);
Point p2 = new Point( 20, 20);
Console.WriteLine(p1.ToString());
Console.WriteLine(p1.GetType());
Console.WriteLine(p1.CompareTo(p2));
IComparable compare = p1;
Console.WriteLine(compare.GetType());
Console.WriteLine(p1.CompareTo(compare));
p2 = (Point)compare;
Console.WriteLine(p2.ToString());
}
}
这个例子发生了3次装箱,1次拆箱,大家用兴趣可以看看到底哪里发生装箱拆箱