程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 黑馬程序員——1C#引用類型與值類型淺析

黑馬程序員——1C#引用類型與值類型淺析

編輯:C#入門知識

 ASP.Net+Android+IO開發.Net培訓

1引言

        對值類型和引用類型理解,是理解C#語言基礎的重要主題之一。這裡會介紹一下內容:

    • 1)值類型和引用類型的內存分配情況
    • 2)什麼時候用值類型,什麼時候用引用類型。
    • 3)裝箱與拆箱

 1.1值類型與引用類型內存分配

      值類型:值類型實例要麼分配在棧上,要麼分配在堆上(此時以類型的字段存在托管堆上)。值類型包括簡單類型、結構等。定義值類型用關鍵字Struct。(由於值類型均是密封的,意味著所有定義的值類型均繼承字ValueType,且不能派生,但是可以實現接口),如果值類型實例分配在棧上,那麼方法調用退出後則銷毀;若位於GC堆上,則隨其所在對象消亡而消亡,主要由GC控制。由於值類型本身包含值,通常分配在棧上,訪問無需地址轉換,分配空間自動釋放,所以值類型的效率更高。

      Main(= = = Student(,, 
     
      
         
           
         
          
     
     
         
         
          {  _firtName+ Sex _sex= 
         
         {  
         
          Age { ;  
         
          
         
         
         
         
         
         Student( argFirstName,  argLastName, ==== 
     
      
         
 
         
 
         
 
         

值類型變量a,和引用類型變量stu所引用的實例內存概況如下圖

 

  1.2什麼時候用值類型,什麼時候用引用類型?

           引用類型有行為、有多態、有繼承。可以發現只要用到struct的場合,基本都可以用class替代。那麼為什麼還要有值類型呢?答案顯而易見是效率問題。我們知道引用類型分配在堆上,而堆上的每個對象都有額外的一些成員(同步索引塊,類型對象指針(指向類型對象的方法表)),這些都要初始化;另外從托管堆上分配一個對象,可能強制執行一次垃圾回收操作。由上可見軟件系統的所有類型全是引用類型,那麼引用程序的性能會顯著下降。而值類型通常分配在棧上,通常為較小的帶有數值含義的數據結構,訪問的時候不需要像訪問對象那樣通過引用類型變量查找,使用完也是自動釋放,這樣效率就會很高。

           通常定義類型的時候應該優先考慮值類型,因為它的效率更高。值類型一般在以下場合使用:

                1類型本身數據量較小,且主要用於存儲數據,表現出明顯的數值含義。

                2類型不需要從其他任何類型繼承(接口除外),也不派生出任何其他類型

 相反,選用引用類型的時候會考慮其 1本身數據結構較大;2可能會擴展(即會派生)。目前個人知識有限,貌似也只能想到這兩點。

 

3裝箱與拆箱

              1概念:裝箱與拆箱,就是值類型與引用類型的轉換。裝箱就是值類型數據轉換為引用對象,可以將值類型視為對象來處理,通常轉換為Object類型的或者該值類型實現的任何接口引用類型;拆箱就是引用類型轉換為值類型,通常伴隨著從堆中復制對象的數據字段的操作。注:只有被裝過箱的對象才能被拆箱。

             2先看一段代碼

          {
            int x = 100;
            object o = x;//裝箱
            int y = (int) o;//拆箱
        }

            裝箱過程三步曲:

  • 內存分配:  在托管堆中分配內存空間,內存大小為待裝箱值類型的大小加上其他額外的內存空間(主要為類型對象指針和同步索引塊)
  • 實例拷貝:將值類型的字段值拷貝到新分配的內存中
  • 引用返回:將托管堆中的對象地址返回給新的引用類型變量 (即例子中的對象o)

           拆箱過程兩部曲

  •  實例檢查:檢查對象是否為null,檢查對象是否為給定值類型的裝箱值,不滿足檢查條件拋異常。
  •  取數據字段地址:從實例中獲取數據字段的地址(本例中為o中存儲100至的地址)
  •  值拷貝:根據獲取的數據字段地址將值拷貝到基於棧的值類型的實例中(本例中的y)

   總結:裝箱拆箱會帶來大量的性能損失,我們平時寫程序的時候應盡可能用FCL提供的重載方法或者泛型。如大家經常用的StringBuilder 用來拼接大量的字符串 比用"+"性能要高的多。 

ASP.Net+Android+IOS開發.Net培訓

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved