static void Main(string[] args)
{
A a = new A();
a.i = 1;
object o = 1; Change(a); Change(o); Console.WriteLine("object:{0}; A:{1}",
((int)o).ToString(),
a.i.ToString());
} static void Change(object o)
{
o = 5;
} static void Change(A i)
{
i.i = 5;
}
结果:// ------------------------
object:1; A:5引用类型做函数的参数在调用函数时传递的是实例的引用,因此在函数中对引用类型做改动会影响到函数生命期外。
但是在将一个值类型装箱后同样的操作缺得到了不同的结果。在这个问题上对clr的处理机制感到迷惑,请高手指点
{
public int i;
}
这跟我理解的装箱操作有些出入
static void Change(object o)
{
o = 5;
}
传入的是一个引用的拷贝,你改变拷贝并不能改变引用本身。它跟static void Change(A i){ i.i = 5; }的区别在于:
虽然A i传入的也是一个引用的拷贝,但这个拷贝和正本都指向了同一个托管对象,修改了拷贝的成员i,等于修改了正本的成员i。
2、装箱并不是创建一个对象并简单的保存值类型的指针。
原因很简单,值类型一般生存在堆栈里,堆栈在当前方法完成后就回卷了,
而作为装箱对象,必须能独立于堆栈存在,比如装箱对象必须从方法中返回后还能使用。因此,记得装箱时候用的是拷贝。
恩,明白了,o = 5 其实是改变了引用,而并没有改变实例
这就跟 static void Change(A i)
{
i = new A();
i.i = 5;
}
一样,傻掉了
对于你说的第二点,我的理解是装箱后,栈上的值类型复制了一份拷贝到堆上,object指向的是这个堆上的副本
Change(o);,在栈中创建一个object o,o保存的是堆中存放1的地址。
static void Change(object o)
{
o = 5;
}
传入的是一个引用的拷贝,你改变拷贝并不能改变引用本身。 它跟static void Change(A i){ i.i = 5; }的区别在于:
虽然A i传入的也是一个引用的拷贝,但这个拷贝和正本都指向了同一个托管对象,修改了拷贝的成员i,等于修改了正本的成员i。
2、 装箱并不是创建一个对象并简单的保存值类型的指针。
原因很简单,值类型一般生存在堆栈里,堆栈在当前方法完成后就回卷了,
而作为装箱对象,必须能独立于堆栈存在,比如装箱对象必须从方法中返回后还能使用。 因此,记得装箱时候用的是拷贝。
非常同意。3楼高人