“引用类型”做函数参数,在函数中可以被处理并保留值。比如:
class box
{
        public int i = 0;
}
class main
{
   private void setbox(box bb)
   {
        bb.i = 2;
   }   main()
   {
        box b = new box();
        setbox(b);
        MessageBox.Show(b.i.ToString());
   }}
这里输出的b.i的值已变为2.
而将一个“值类型”变量,装箱成“引用类型”,却无法通过传递参数来改变值。比如:
class main
{
   main()
   {
       int i = 0;
       object box = i;
       Set(box);       MessageBox.Show(box.ToString());
   }   private void Set(object aBox)
   {
       aBox = 2;
   }
}
这里输出的box和i的值依然是0.为什么?

解决方案 »

  1.   

    对一个值进行装箱是指编译器在托管堆中创建一份该值得副本,并将副本的地址赋予Object类型的变量或参数,这样就可以将值类型用作引用类型。
    这种形式是和Class实例化后的内存存放一样的。同样是在堆中放数据。传递给函数时,应该也是传变量的地址,在函数中的更改也是写入地址对应的堆中,并在函数结束后值被保留下来。但实际上却不是这样,令人费解。
      

  2.   

    object存储的是那个箱子的地址,可你第二段代码中set方法参数传递的时候是值传递,也就是说abox和box是堆栈上两个独立的指针变量,都存储了同样的地址值。你改动了abox存储的地址值而已,并没有修改box存储的地址值,这样box始终是指向那个装箱的0的。
      

  3.   

    你第一段代码同样采用了值传递的参数,但你修改的是共同指向的托管堆上的类成员。所以两段代码没有可比性。你把第一段bb.i=2;换成 bb=new box(); bb.i=2;就有点像第二段代码的样子了,这样第一段代码也会显示0。
      

  4.   

    那请问我如何在第二段代码中实现第一段代码的情况? 不用ref.
      

  5.   

    不用ref就用out...C#中只有这两种方式...如果在为方法声明参数时未使用ref或out,则该参数可以具有关联的值。可以在方法中更改该值,但当控制传递回调用过程时,不会保留更改的值。通过使用方法参数关键字,可以更改这种行为。
    ------MSDN 这是基础...
      

  6.   

    感谢大家的帮助.我现在明白了.引用类型的变量不直接包含其数据;它包含的是对其数据的引用。当通过值传递引用类型的参数时,有可能更改引用所指向的数据,如某类成员的值。但是无法更改引用本身的值;也就是说,不能使用相同的引用为新类分配内存并使之在块外保持。若要这样做,应使用 ref 或 out 关键字传递参数。(MSDN)第二段中
    private void Set(object aBox) 

        aBox   =   2; 

    只是将临时地在堆中新建一个变量副本存放一个2,并让对象box暂时指向(或引用)这个2. 但这个指向的改变是无法保留下来,随着函数的结束,box又指回(或引用)原来的0.代码object box = i;确实是创建了一个引用类型变量box,并在堆中新建一个副本存放一个0.而此时i依然是i,它与新建的box以及box指向的值已没有关系,只是box指向的值copy于i的值.