c#拆箱跟裝箱

來源:互聯網
上載者:User

標籤:style   io   ar   os   sp   for   strong   資料   div   

Net的類型分為兩種,一種是實值型別,另一種是參考型別。這兩個類型的本質區別,實值型別資料是分配在棧中,而參考型別資料分配在堆上。那麼如果要把一個實值型別資料放到堆上,就需要裝箱操作;反之,把一個放在堆上的實值型別資料取出來,則需要進行拆箱操作。

例如,對於如下簡單的裝箱和拆箱動作陳述式。

    int i = 123;

    object obj = i;//Boxing

 if( obj is int )

        int  j = (int) obj;//Unboxing

為了,更好的詮釋裝箱和拆箱操作,我借用MSDN關於“Boxing”的解釋圖,具體如下。 

明白了這兩名詞的意思,現在說說為什麼要減少裝箱和拆箱操作。

原因有兩個,主要是關於效率:一個就是對於堆的操作效率比較低;另一個就是對於堆上分配的記憶體資源,需要GC來回收,從而降低程式效率。

考慮到這兩點因素,那麼需要在程式中減少裝箱和拆箱操作。

如何減少呢,涉及到這兩個操作比較多的是,格式化輸出操作,例如:String.Format,Console.WriteLine之類的語句。

例如:

    Console.WriteLine( "Number list:{0}, {1}, {2}",

        1,2,3 );

對於“1,2,3”來說,相當於前面的“123”一樣,需要經過裝箱和拆箱兩個操作。那麼如何避免呢,其實只要向WriteLine傳遞參考型別資料即可,也就是按照如下的方式。

    Console.WriteLine( "Number list:{0}, {1}, {2}",

        1.ToString(),2.ToString(),3.ToString() );

由於“1.ToString()”的結果是String類型,屬於參考型別,因此不牽扯裝箱和拆箱操作。

其次,牽扯到裝箱和拆箱操作比較多的就是在集合中,例如:ArrayList或者HashTable之類。

把實值型別資料放到集合中,可能會出現潛在錯誤。例如:

    public struct Person

    {

        private string _Name;

        public string Name

        {

            get{ return _Name; }

            set{ _Name = value; }

        }

 

        public Person( string PersonName )

        {

            _Name = PersonName;

        }

 

        public override string ToString()

        {

            return _Name;

        }

 

    }

    // Using the person in a collection

    ArrayList arrPersons = new ArrayList();

    Person p = new Person( "OldName" );

    arrPersons.Add( p );

   

    // Try to change the name

    p = ( Person ) arrPersons[0] ;

    p.Name = "NewName";

 

    Debug.WriteLine( ( (Person ) arrPersons[0] ).Name );//It‘s "OldName"

有人可能會說,是否可以按照如下的方式去修改呢。

( (Person ) arrPersons[0] ).Name = "NewName";//Can‘t be compiled

很不幸,如上操作不能通過編譯。為什麼呢,對於“( (Person ) arrPersons[0] )”來說,是系統用一個臨時變數來接收拆箱後的實值型別資料,那麼由於實值型別是分配在棧上,那麼操作是對實體操作,可是系統不允許對一個臨時實值型別資料進行修改操作。

    // Using the person in a collection

    ArrayList arrPersons = new ArrayList();

    Person p = new Person( "OldName" );

    arrPersons.Add( p );

   

    // Try to change the name

    p = ( Person ) arrPersons[0] ;

    p.Name = "NewName";

 arrPersons.RemoveAt( 0 );//Remove old data first

    arrPersons.Insert( 0, p );//Add new data

    Debug.WriteLine( ( (Person ) arrPersons[0] ).Name );//It‘s "NewName"

其實,這樣操作會產生過多裝箱和拆箱操作。那麼更好的方法,可以通過介面來完成,從而減少裝箱和拆箱操作。對於這個例子的介面實現應該如下。

    public interface IPersonName

    {

        string Name{ get;set;}

    }

 public struct Person:IPersonName

    {

        private string _Name;

        public string Name

        {

            get{ return _Name; }

            set{ _Name = value; }

        }

 

        public Person( string PersonName )

        {

            _Name = PersonName;

        }

 public override string ToString()

        {

            return _Name;

        }

    }

// Using the person in a collection

    ArrayList arrPersons = new ArrayList();

    Person p = new Person( "OldName" );

    arrPersons.Add( p );

   

    // Change the name

    ( (IPersonName)arrPersons[0] ).Name = "NewName";

 Debug.WriteLine( ( (Person ) arrPersons[0] ).Name );//It‘s "NewName"

很多人就問,為什麼實值型別不能修改,即

( (Person ) arrPersons[0] ).Name = "NewName";//Can‘t be compiled

而如上的介面類型就能修改呢,即

( (IPersonName)arrPersons[0] ).Name = "NewName";

這是由於產生的臨時變數的類型不同,前者已經在前面進行說明了,後者由於產生的臨時變數的類型為IPersonName,屬於參考型別,那麼相當於臨時變數就是原對象的引用,那麼對於對於它的修改會直接修改到原對象,因此是可以的。可以說這裡的不同本身在於產生臨時對象的類型不同,從而造成本質的區別。

通過介面來改寫,這樣就減少了裝箱和拆箱操作,同時也保證了修改的正確性。不過要注意的是,這裡介面對於的是參考型別,如果介面訪問的或者返回的是實值型別,那麼用介面雖說能實現了,但是對於裝箱和拆箱操作來說,並沒有減少。

對於裝箱和拆箱操作來說,基本上就講完了,只要記住頻繁裝箱和拆箱操作會降低程式效率,因此在編寫的時候要盡量避免。

c#拆箱跟裝箱

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.