public  class Program
    {
        static void Main(string[] args)
        {
            MyClass a = new MyClass();
            a.a="A";
            Console.WriteLine(a.a);
            MyFunction(a);            Console.WriteLine(a.a);
            Console.Read();        }        public static void MyFunction(MyClass a)
        {
            //MyClass b = new MyClass();
            //b.a = "B";
            //a = b;            a.a = "b";
            Console.WriteLine(a.a);
        }
    }    public class MyClass
    {
        public string a = "";
    }
注释前输出  A b A
注释后      A b b
a=b这句话 的过程是不是将a堆的指向指向了b的堆?

解决方案 »

  1.   

    第一种情况,MyFunction的a是不允许修改的,执行完MyFunction,a的值是不变的
      

  2.   

    对于方法内部对传入引用类型的形参重新赋值,是不会影响到实参的。可见MSDN ref out 部分。
      

  3.   

    注释前你的代码涉及了两个对象,MyFunction里面改动的对象是新建的。注释后你的代码就涉及了一个对象,MyFunction里面操作的就是那个唯一的对象
    传递参数时候,拷贝的仅仅是引用,实参和形参虽然是不同的引用,但指向的是同一个MyClass对象
      

  4.   

    传递参数时候,拷贝的仅仅是引用,实参和形参虽然是不同的引用,但指向的是同一个MyClass对象难道是这样?
    因为第一个形参的引用地址被改变了,指向了b,跟实参地址不同,所以无法影响实参,而注释后因为地址还是同一个地址,所以形参变化会导致实参变化?
      

  5.   

    注释前,a = b把a指向了b, 下面的a.a = "b";其实改变的是b实例中的值,又因为传递参数是没有用ref所以实参的地址不会被改变,所以退出函数以后a实例中的a值还是"a";注释后,把a 所指向的地址中的值被改成了"b",所以退出函数后值仍然是"b";
      

  6.   


    你觉得a=b的过程是改变的是a堆的地址还是栈的地址呢
      

  7.   

    改变的是堆的地址,因为用new申请的变量一般都在堆上
      

  8.   


    注释后,没有改变地址,只改变了地址中的值。
    注释前,有两个地址a和b, a=b把b的地址给了a (也可以说是指针a指向了b), 之后的操作改变的是地址b中的值,地址a中的值没有变。
      

  9.   

    有一点可能没说清楚,MyClass a = new MyClass();中的a是一个地址(也可以说是指针),而string类型的a才是地址中的值。
      

  10.   

    恩恩,我说错了,改变的是堆中的值,我是想说,两种情况都是改变了堆。我说说我的看法吧,其实我觉得作为参数传进来,其实传的是a的堆地址,注释前由于试图去改变a堆地址,将其指向b的堆,所以方法执行完后,对main函数中的a没有影响,应为a的堆内容没有变。
    注释后直接更改了a堆的内容,所以main中有影响如果加ref 传进来,则传的是栈地址,不管是改变堆地址还是改变堆内容传出去后都会影响a
      

  11.   

    你给出的代码与ref和out没有半点关系
      

  12.   


    是啊,是跟ref没有关系,但是应该想到ref时是什么情况!
      

  13.   

    如果用了ref 你在MyFunction中操作的a就是Main中的a,其实你可以不考虑地址的问题。如果牵扯到地址,理解起来就很费劲。
      

  14.   

    这还是.NET方法参数默认按值传递的问题...去看这个...【.NET版月经问题】之二【引用类型参数就是按引用传递吗?】
      

  15.   

    MyFunction(ref a);        public static void MyFunction(ref MyClass a)
            {
                //MyClass b = new MyClass();
                //b.a = "B";
                //a = b;            a.a = "b";
                Console.WriteLine(a.a);
            }这样前后就一样了
      

  16.   

    我感觉楼主是钻牛角尖了。
    虽然这里的传递是引用传递,不用ref关键字,你修改属性是可以,但是修改传递的变量本身的指向就不行。调用方传递变量a给函数MyFunction,实际只是传递了那个变量a所指的地址,如果加了ref关键字,不但传所指地址,还传了a变量本身。因此你在函数中想要修改a变量的指向是无效的,函数中获得的a变量于调用方的a变量是2个变量,虽然指向了同一个地址,你把函数中的a变量的指向改变了,不会影响调用方的a变量的指向,结果预期所示。
      

  17.   


    不同之处在于,对形参赋值还是对形参属性赋值。
    a = b; 对形参赋值(并不会修改实参的引用)
    a.a = "b"; 对形参属性赋值(实参的属性被修改)
      

  18.   

    重新new了一个对象,地址都变了当然不同