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。

      至此,我總結出:值傳遞是傳遞棧中的值;引用傳遞是傳遞棧地址。

      這一次我是蠻認真的寫的這篇博客,但願人氣能好一點,不吝留言賜教的話就感激涕零了。

相關文章
相關標籤/搜索