C#基础原理拾遗——引用类型的值传递和引用传递

      之前写博客不深动,只搭个架子,像作笔记,没有本身的思考,也没什么人来看。这个毛病得改,就从这一篇开始…html

      最近准备面试,深感基础之重要,奈何我不是计算机科班出身,基础方面有些捉襟见肘。短时间怎么补?作面实题呗。遇到哪儿没理解透,本身查资料,印象深入。这个问题就是这么来的。原题很简单:“对于方法,参数传递分为值传递和____两种。”这还不简单,但我得拓展啊,得思考啊…面试

      如下一、2是个人意淫,但记录本身的一些错误想法并思考改正仍是有益处的,但愿不会对你们有误导。以为麻烦的话能够直接看3。ide

一、什么是值传递和引用传递?idea

      我一开始的理解是,值类型根本没有引用啊,它能有引用传递?它的值传递和引用传递应该是同样的。至于引用类型,它的值传递应该是一个深拷贝,引用传递应该是一个浅拷贝。对于这一类比,最初还颇感得意。但查资料才知道,What a stupid idea!没办法,非科班出身,知识不成体系,有盲点,但我知道这不是借口,这不在大补嘛,补得跟小鸡子似的。spa

      看了http://www.cnblogs.com/whc-blog/archive/2011/07/20/2111803.html这篇,感性的知道了什么是值传递和引用传递。其实也不是压根不知道,长时间不用忘了,而后就出现了上面离奇的想法。code

      其实在整个思考完了之后我给值传递和引用传递下了个定义,在这里先搬出来:(欢迎你们批评指正)htm

值传递是传递栈中的值;引用传递是传递栈地址。对象

二、引用类型的值传递和引用传递能够类比成深拷贝和浅拷贝吗?blog

     到此对于这个问题仍是有疑问的,就写了个小Demoget

class Program
    {
        static void Main(string[] args)
        {
            Student xiaohong = new Student("小红", 12);
            BanZheng(ref xiaohong);
            //BanJiaZheng(xiaohong);
            Console.WriteLine(xiaohong.Name + "  " + xiaohong.Age);
            Console.ReadKey();
        }

       //办证
        static void BanZheng(ref Student student)
        {
            student.Name = "红姐";
            student.Age = 18;  
        }
       //办假证
        static void BanJiaZheng(Student student)
        {
            student.Name = "红姐";
            student.Age = 18;       
        }
    }

    class Student
    {
        public Student(string name, int age)
        {
            Name = name;
            Age = age;
        }
        public string Name { get; set; }
        public int Age { get; set; }
    }

      解释一下:小红今年12,但她要工做,可能家庭困难吧。一、若是她有关系(有关系还家庭困难?解释不了),找到BanZheng方法,给她身份证改为“红姐”18,拿去Main方法输出验证,果真输出“红姐”18。呵呵。但按我理解,ref若是是浅拷贝的话,Age做为一个值类型属性应该是从新烤了一份,其值不该该回传给xiaohong啊,应该输出“红姐”12。看来有关系就是牛逼啊。二、若是她不要紧,找了个办假证的BanJiaZheng,一验证仍是“红姐”18,若是按我理解,值传递是深拷贝的话,student参数应该和xiaohong是两个彻底不一样的对象,应该输出“小红”12,看来这个认证机构(个人理解)有水。因而我再查资料…

三、引用类型的值传递和引用传递揭秘

     功夫不负有心人,找到这么一篇好文http://www.cnblogs.com/duanwg/archive/2006/07/21/456247.html,其实看了它就能理解了,但我仍是根据上面的Demo作些改进,加深理解。

class Program
    {
        static void Main(string[] args)
        {
            Student xiaohong = new Student("小红", 12);
            BanZheng(ref xiaohong);
            //BanJiaZheng(xiaohong);
            Console.WriteLine(xiaohong.Name + "  " + xiaohong.Age);
            Console.ReadKey();
        }

        static void BanZheng(ref Student student)
        {
            //student.Name = "红姐";
            //student.Age = 18;

            student = new Student("红姐", 18);       
        }

        static void BanJiaZheng(Student student)
        {
            //student.Name = "红姐";
            //student.Age = 18;

            student = new Student("红姐", 18);           
        }
    }

    class Student
    {
        public Student(string name, int age)
        {
            Name = name;
            Age = age;
        }
        public string Name { get; set; }
        public int Age { get; set; }
    }

      这一次办证方法改了,在方法体中student = new Student(…)。再到Main方法中验证一下,若是调用BanZheng方法,输出“红姐”18,若是调用BanJiaZheng方法,输出“小红”12。看来有关系到何时都很牛逼啊。

      画两个图理解一下:

(1)若是是BanJiaZheng,即值传递的话:

捕获

变量xiaohong和student的栈中有相同的堆地址,都指向10000,即“小红”12,而在BanJiaZheng方法中student = new Student(…),开辟了10010堆,student的栈中的堆地址改成10010,而xiaohong的栈中堆地址仍是10000。因此方法调用后xiaohong指向的对象没变,依然是“小红”12。

(2)若是是BanZheng,即引用传递的话:

捕获1

变量xiaohong和student指向同一栈地址,在student = new Student(…)后,该栈001指向新的堆地址10010,而xiaohong也指向001栈。因此方法调用后xiaohong指向的对象变成了“红姐”18。

      至此,我总结出:值传递是传递栈中的值;引用传递是传递栈地址。

      这一次我是蛮认真的写的这篇博客,但愿人气能好一点,不吝留言赐教的话就感激涕零了。

相关文章
相关标签/搜索