class Program
    {
        static void Main(string[] args)
        {
            Person p1 = new Person();
            p1.Age = 10;
            p1.Name = "Jim";
            Console.WriteLine(p1.Age+p1.Name);
            change(p1);
            Console.WriteLine(p1.Age + p1.Name);
            string s1 = "ssssssssssss";
            Console.WriteLine(s1);
            changestring(s1);
            Console.WriteLine(s1);            Console.ReadKey();
        }        static void change(Person p)
        {
            p.Age = 999;
            p.Name = "bill gates"; 
        }
        static void changestring(string s)
        {
            s = "fuck you";
        }
    }
    class Person
    {
        public int Age { get; set; }
        public string Name { set; get; }
    }
-------------------输出结果-----------------
10Jim
999bill gates
ssssssssssss
ssssssssssss我自己定义了一个Person类,两个方法
我的问题是:关于方法参数(两个方法的参数都是值传递,没有加ref和out ,但是change()方法能改变Person 变量,当changestring()方法不能改变string变量,这是为什么呢方法参数stringclass

解决方案 »

  1.   

    person和string都是引用类型,传递的都是引用地址,所以person类型改了,但是string类型有个特性,任何对string的操作都会生成他的副本而不是在原来基础上修改。所以s1不变
      

  2.   

    这就是盲人摸象的解释。仔细看下面两个方法的区别
            static void change(Person p)        {            p.Age = 999;            p.Name = "bill gates";         }        static void changestring(string s)        {            s = "fuck you";        }
    前一个方法和后一个方法现在不是等价的,因为前一个是改对象内部的属性,另一个是改对象本身。
    把前一个方法修改下才是等价的,你再看结果。
           static void change(Person p)      
      {        
    p = new Person();     
    p.Age = 999;           
     p.Name = "bill gates";   
          }
      

  3.   

    因为Person是引用类型的,所以函数类改了值,函数外也随之改变
      

  4.   

    哥啊,string也是引用类型啊,这点我可以保证
      

  5.   

    string其实是只读的,给string赋值其实是让他指向一个新的实例而已。main方法string还是指向原来的实例并没影响
      

  6.   

    string 引用类型是比较特殊的,给string赋值会指向一个新的实例
      

  7.   

    厉害,还真是这样!!!那能不能改变string的内部呢? 
      

  8.   

    这就涉及到另一个问题了。string这个引用类型有没有内部呢?
    比如"abc"这个字符串我想在后面加一个"d",变成"abcd"。非常可惜,由于string的实现机制,所以"abc"和"abcd"是两个完全不同的对象,所以 其实还是相当于引用本身发生了变化。
      

  9.   

    非常感谢,string就是只读的吧,声明一次就写死了。比如:string s="abc"; 就是说s指向的是内存中一块只读的数据"abc",这块数据不能改变,不知道我的理解对否?
      

  10.   

    Person是引用类型,实例化(new)对象时,会在内存堆中开辟一个空间,有实例化对象指向它,通过函数传递引用类型时,是传递引用类型对应在内存堆指向的地址,在change函数中修改p1时,是修改p1在内存堆中的引用,所以修改完之后,在Main函数再次使用p1时,因为p1的指向内存堆的地址一直没有变,所以调用到的值是p1修改过的内容。
    string也是引用类型,但是它跟其它引用类型有所不同,string类型变量的值直接是存储在栈中,通过函数传递的是s1的副本,也是就说传递之前会在栈里面新建一个s1的副本传递到changestring函数中,在
    changestring函数中对s1做的任何修改都不会影响Main函数中的s1,所以在Main函数在s1修改前后的值都是不变的
      

  11.   

     class Program
        {
            static void Main(string[] args)
            {
                Person p1 = new Person();
                p1.Age = 10;
                p1.Name = "Jim";
                Console.WriteLine(p1.Age + p1.Name);
                change(p1);
                Console.WriteLine(p1.Age + p1.Name);
                string s1 = "ssssssssssss";
                Console.WriteLine(s1);
                changestring(s1);
                Console.WriteLine(s1);            Console.ReadKey();
            }        static void change(Person p)
            {
                p = new Person(); //这里如果new出来一个,那主是代表新的person对象了
                p.Age = 999;
                p.Name = "bill gates";
            }
            static void changestring(string s)
            {
                s = "fuck you";
            }
        }
        class Person
        {
            public int Age { get; set; }
            public string Name { set; get; }
        }
    我用你的思路,弄了一个你“认为”会错的东西,仔细看代码,估计能解决你的问题
    显示结果:
    10Jim
    10Jim
    ssssssssssss
    ssssssssssss上面如果不new一个persion对象,那么指针还是指向Person p1 = new Person();这里
    如果改成你要的可以这样:
        class Program
        {
            static void Main(string[] args)
            {
                Person p1 = new Person();
                p1.Age = 10;
                p1.Name = "Jim";
                Console.WriteLine(p1.Age + p1.Name);
                change(p1);
                Console.WriteLine(p1.Age + p1.Name);
                string s1 = "ssssssssssss";
                Console.WriteLine(s1);
                s1 = changestring(s1);
                Console.WriteLine(s1);            Console.ReadKey();
            }        static void change(Person p)
            {
                //p = new Person(); //这里如果new出来一个,那主是代表新的person对象了
                p.Age = 999;
                p.Name = "bill gates";
            }
            static string changestring(string s)
            {
                s = "fuck you";
                return s;
            }
        }
        class Person
        {
            public int Age { get; set; }
            public string Name { set; get; }
        }
    输出:
    10Jim
    999bill gates
    ssssssssssss
    fuck you
      

  12.   


    string类型比较特殊,事实上任何一个string都是全局的。所谓的修改string的值,其实就是把引用更改到另一个string上去。
    事实上平时你不需要关心这个,但是有一种情况必须知道,就是lock。
    一般用lock来锁引用类型的对象,但是不应该去lock一个string的对象,因为string是全局的,
    string a = "abc";
    所以如果你lock(a),事实上"abc"这个对象就锁住了,另外一个地方
    string b = "abc";
    lock(b);
    这时a和b其实是锁的同一个对象。所以lock是不推荐去锁string的。