亚洲免费在线-亚洲免费在线播放-亚洲免费在线观看-亚洲免费在线观看视频-亚洲免费在线看-亚洲免费在线视频

裝箱與值類型雖然很容易理解,但是在實(shí)際使用中

系統(tǒng) 1817 0
          public struct Point 

    {

        private int m_x, m_y;



        public Point(int x, int y) 

        {

            m_x = x;

            m_y = y;

        }



        public override string ToString()

        {

            return string.Format("{0},{1}", m_x, m_y);

        }

    }


    
上面是一個(gè)值類型的定義,下面創(chuàng)建一個(gè)實(shí)例,用在控制臺(tái)上輸出一些信息:
                  Point p = new Point(1, 1);

            Console.WriteLine(p);


    
這與
                  Point p = new Point(1, 1);

            Console.WriteLine(p.ToString());


    
這二者在輸出結(jié)果上完全一樣,也許很多人象我一樣,在平時(shí)工作中隨意使用,也不會(huì)去管它有什么不同?
但其實(shí),Console.WriteLine(p)是會(huì)產(chǎn)生裝箱(box)指令的!

原因很簡(jiǎn)單:Console.WriteLine的所有重載版本中,并沒(méi)有一個(gè)Console.WriteLine(Point p)的版本,所以默認(rèn)會(huì)調(diào)用Console.WriteLine(Object o)這個(gè)版本,p會(huì)裝箱成Object,返回一個(gè)在堆上的引用。
而Console.WriteLine(p.ToString())則會(huì)調(diào)用Console.WriteLine(String s)這個(gè)重載版本,p.ToString()已經(jīng)是一個(gè)String了,所以無(wú)需裝箱。

繼續(xù)來(lái)看一段稍微長(zhǎng)一點(diǎn)的代碼:
        using System;



namespace boxTest

{

    class Program

    {

        static void Main(string[] args)

        {

            int i = 1;

            test(5);

            Console.WriteLine(i);//1



            object obj = 1;           

            test(obj);

            Console.WriteLine(obj);//1



            string s = "1";

            test(s);

            Console.WriteLine(s);//"1"



            P1 p1 = new P1(1);

            test(p1);

            Console.WriteLine(p1.X);//1



            P2 p2 = new P2(1);

            test(p2);

            Console.WriteLine(p2.X);//5



            Console.Read();

        }



        static void test(int i)

        {

            i = 5;

        }



        static void test(object o)

        {

            o = 5;

        }



        static void test(string s)

        {

            s = "5";

        }



        static void test(P1 p)

        {

            p.X = 5;

        }



        static void test(P2 p) 

        {

            p.X = 5;

        }

    }



    internal struct P1

    {

        private int _x;



        public P1(int x)

        {

            _x = x;

        }

        public int X { set { _x = value; } get { return _x; } }

    }



    internal class P2

    {

        private int _x;



        public P2(int x)

        {

            _x = x;

        }

        public int X { set { _x = value; } get { return _x; } }

    }

}


      
上面代碼的5次輸出結(jié)果,您都猜對(duì)了嗎?

1 次輸出:因?yàn)閕是值類型,參數(shù)傳遞默認(rèn)是按值傳遞的,也就是說(shuō)test方法體里的參數(shù)i是一個(gè)全新的副本,跟外界沒(méi)關(guān)系,方法調(diào)用完后,方法體內(nèi)的i自動(dòng)被清理,不影響方法體外的i

2 次輸出:雖然Object是引用類型,參數(shù)傳遞也是按引用傳遞的,但是方法體內(nèi)o=5的賦值,使o指向了一個(gè)全新的"已裝箱的5",這時(shí)o與方法體外的obj已經(jīng)是二個(gè)不同的對(duì)象了,有懷疑的同學(xué),可用Object.ReferenceEquals方法輸出驗(yàn)證,如下面這樣
        static void test(object o)

        {

            object o1 = o;

            Console.WriteLine(Object.ReferenceEquals(o1, o));//true

            o = 5;

            Console.WriteLine(Object.ReferenceEquals(o1, o));//false

        }


      
但是在test(Object o)調(diào)用完成后,main方法后面還要繼續(xù)使用obj(因?yàn)橛蠧onsole.WriteLine(obj)),所以obj此時(shí)也不會(huì)被列為垃圾回收的目標(biāo)。test方法調(diào)用結(jié)束后,方法體內(nèi)部的對(duì)象o,因不再使用將等候GC回收。

3 次輸出:String雖然也是引用類型,但是String的處理機(jī)制有別于其它引用類型(這個(gè)話題展開(kāi)就可再寫一篇文章了,建議不清楚的同學(xué)去CLR VIR C#中的"字符、字符串和文本處理"相關(guān)內(nèi)容),在test(String s)內(nèi)對(duì)s賦值為新字符串時(shí),同樣會(huì)生成一個(gè)新的對(duì)象,因此也不會(huì)影響到test方法體外的值。但是:跟第2次輸出不同的是,test(String s)調(diào)用結(jié)束后,字符串"5"卻不會(huì)被立即回收(即:字符串駐留機(jī)制),如果下次有人需要再次使用字符串"5",將直接返回這個(gè)對(duì)象的引用,這一點(diǎn)可通過(guò)觀察對(duì)象的HashCode看出端倪:
        using System;



namespace boxTest

{

    class Program

    {

        static void Main(string[] args)

        {

            string s = "1";

            test(s);           



            string s1 = "1";

            string s2 = "5";



            Console.WriteLine("{0},{1},{2}", s.GetHashCode(), s1.GetHashCode(), s2.GetHashCode());



            Console.Read();

        }



       



        static void test(string s)

        {

            Console.WriteLine("{0}", s.GetHashCode());

            s = "5";

            Console.WriteLine("{0}", s.GetHashCode());

        }        

    }    

}


      

輸出結(jié)果為:

-842352753
-842352757
-842352753,-842352753,-842352757

4 次輸出:struct類型的P1是值類型,類似第1次輸出中的解釋一樣,按值傳遞,方法體內(nèi)修改的只是副本的值,也不會(huì)影響test體外的值.

5 次輸出:class類型的P2是引用類型,參數(shù)傳遞的其實(shí)是p2的地址(即指針),而且在test方法體內(nèi)并未對(duì)p2重新賦值(指沒(méi)有類似p2 = new P2(1)類似的代碼),而只是修改了p2的屬性X,方法調(diào)用結(jié)束后,p2引用指向的地址沒(méi)有改變,但是這個(gè)地址中對(duì)應(yīng)的值X已經(jīng)變了,所以輸出5.

最后再來(lái)二個(gè)CLR VIR C#原書示例的簡(jiǎn)化版
        using System;



namespace boxTest

{

    class Program

    {

        static void Main(string[] args)

        {

            P p1 = new P(1);

            Console.WriteLine(p1);//1



            p1.ChangeX(2);

            Console.WriteLine(p1);//2



            object o = p1;

            ((P)o).ChangeX(5);

            Console.WriteLine(o);//這里將輸出2,而不是5 ! 

            //解釋:((P)o).ChangeX(5); 

            //其實(shí)相當(dāng)于 P p2 = (P)o; p2.ChangeX(5);

            //所以根本沒(méi)改變p1中的_x值(因?yàn)镻是值類型,p2與p1在內(nèi)存中對(duì)應(yīng)的是二個(gè)不同的地址,相互并不干擾),

            //然后臨時(shí)生成的p2因?yàn)椴辉俦皇褂茫琈ain方法執(zhí)行完成后,會(huì)自動(dòng)清理



            Console.Read();

        }         

    }



    struct P 

    {

        private int _x;



        public P(int i) 

        {

            _x = i;

        }        



        public void ChangeX(int x) 

        {

            _x = x;

        }



        public override string ToString()

        {

            return string.Format("{0}", _x);

        }

    }

}


      
?最后一次的輸出,解釋已經(jīng)寫在注釋中了,大家自己體會(huì)。
        using System;



namespace boxTest

{

    class Program

    {

        static void Main(string[] args)

        {

            P p1 = new P(1);

            Console.WriteLine(p1);//1



            p1.ChangeX(2);

            Console.WriteLine(p1);//2



            object o = p1;

            ((IChangeX)o).ChangeX(5);

            Console.WriteLine(o);//這里將輸出5

            //解釋: ((IChangeX)o).ChangeX(5); 相當(dāng)于

            //IChangeX _temp = (IChangeX)o;

            //_temp.ChangeX(5);

            //因?yàn)榻涌趯?shí)際上返回的是引用(算是引用類型),

            //所以這時(shí)_temp與o指向的是同一個(gè)內(nèi)存地址,修改_temp就相當(dāng)于修改o

           



            Console.Read();

        }         

    }



    struct P :IChangeX

    {

        private int _x;



        public P(int i) 

        {

            _x = i;

        }        



        public void ChangeX(int x) 

        {

            _x = x;

        }



        public override string ToString()

        {

            return string.Format("{0}", _x);

        }

    }



    interface IChangeX 

    {

        void ChangeX(int x);

    }

}


      
讓struct實(shí)現(xiàn)一個(gè)接口以后,情況就變了,同樣大家看注釋,不解釋。
?
要想寫出高性能的代碼,每個(gè)細(xì)節(jié)都要意識(shí)到背后發(fā)生的事情。所以象CLR VIR C#這類神作,沒(méi)事拿來(lái)翻翻,不斷加深印象還是很有必要的。

裝箱與值類型雖然很容易理解,但是在實(shí)際使用中,并不總是能100%用對(duì)


更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號(hào)聯(lián)系: 360901061

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對(duì)您有幫助就好】

您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長(zhǎng)會(huì)非常 感謝您的哦!!!

發(fā)表我的評(píng)論
最新評(píng)論 總共0條評(píng)論
主站蜘蛛池模板: 国产福利一区二区三区在线视频 | 亚洲欧美日韩一级特黄在线 | 羞羞视频在线观看 | 欧美精品一区二区三区观 | 来自深渊在线观看 | 人人爽天天碰天天躁夜夜躁 | 亚洲国产成人综合 | 国产欧美一区二区另类精品 | 狠狠操大逼 | 狠狠综合久久久久综合小说网 | 国内精品久久久久影院一蜜桃 | 最新国产一区二区精品久久 | 色综合天天综久久久噜噜噜久久〔 | 99久久精品久久久久久婷婷 | 四虎最新紧急入口 | 欧美日韩免费看 | 亚洲欧美综合一区二区三区四区 | 久久久国产视频 | 亚洲欧美日韩中文v在线 | 国产麻豆永久视频 | 午夜欧美福利视频 | 伊人精品成人久久综合欧美 | 亚洲精品久久片久久 | 在线成人a毛片免费播放 | 日操夜操天天操 | 人人揉人人爽五月天视频 | 国产精品福利在线观看 | 成人在线激情视频 | 丝袜三级 | 成人影院午夜久久影院 | 国产成人精品视频免费大全 | jizz中国人 | 老司机福利深夜亚洲入口 | 国产中文字幕在线免费观看 | 欧美午夜艳片欧美精品 | 91亚洲视频在线观看 | 国产一区二区三区精品视频 | 免费中日高清无专码有限公司 | 欧美日韩免费看 | 99精品福利视频 | 久久久精品久久久久特色影视 |