C#值類型與引用類型

從如下幾個方面總結一下C#的值類型與引用類型:編程

  • 定義
  • 值類型與引用類型的區別
  • 值類型與引用類型的選擇
  • 拆裝箱
  • 如何避免拆裝箱

.Net框架最主要的兩個組成部分是CLR和框架類庫(FCL),而CLR最主要的兩個組成部分部分是CTS(公共類型系統)和CLS(公共語言規範)。簡單來講,CTS就是一種規範,它容許遵照此規範的編程語言能夠存在什麼類型,每種類型是否能夠包含成員、以及能夠包含哪些成員。官方給出的CTS做用以下:數組

  • 創建用於跨語言執行的框架。
  • 提供面向對象的模型,支持在 .NET 實現上實現各類語言。
  • 定義處理類型時全部語言都必須遵照的一組規則。
  • 提供包含應用程序開發中使用的基本基元數據類型(如 Boolean、Byte、Char 等)的庫。

故,C#中的值類型與引用類型就遵循此規範。閉包


定義

  • C# 中的數據類型能夠簡單的分爲值類型(結構、枚舉)和引用類型(類、接口、字符串、數組、委託、指針)。
    • 值類型變量或常量的內容僅僅是一個值,例如整數int,小數float/double,布爾值等,換句話說就是,變量引用的位置就是值在內存中的位置。
    • 引用類型比較複雜,它友兩部分組成:對象和對象引用。而引用類型的變量中的內容存儲的是對‘數據’存儲位置的引用,不是直接存儲‘數據’。
  • 存儲開銷:
    • 值類型所佔內存大小就是存儲字段所需內存。例如Book所需內存就是price、title、author內存的和。
    • 引用類型要求爲引用和對象單獨分配存儲空間。對象除佔用了和字段同樣的字節數以外,還須要額外的管理空間開銷。

值類型實例的賦值老是會進行實例複製。 引用類型變量的賦值只會複製引用。 框架

查閱https://referencesource.microsoft.com,會發現 數值類型、布爾類型、字符類型 其實都屬於Strust類型編程語言


值類型與引用類型的區別

  1. 全部值類型都隱式派生自System.ValueType,它是System.Object的子類,該類確保值類型全部的的成員所有分配在棧上。(如下三個除外)
    • 結構體若是含有引用類型成員,該成員會牽扯到堆的分配
    • 靜態類型,若是一個變量時靜態的,那麼,不管她是什麼類型,都會分配到加載堆上
    • 局部變量被捕獲升級爲密封類(閉包中涉及到)
      因此,「值類型都分配在棧上,引用類型都分配在堆上」是不許確的
  2. 引用類型初始值爲null,值類型初始值爲0.
  3. 值類型不能被繼承,引用類型則能夠
  4. 值類型的聲明週期在其定義域內,離開定義域以後即被銷燬,而引用類型沒法肯定什麼時候被銷燬

裝箱與拆箱

裝箱與拆箱就是值類型與引用類型之間的轉換性能

裝箱過程

int i = 1;
object o = i;
複製代碼
  1. 在堆中申請內存,內存大小爲值類型大小,載加上額外的固定空間(類型對象指針和同步塊索引)
  2. 將值類型的字段值拷貝到新申請的內存中
  3. 返回新引用對象的內存地址

裝箱須要比原數據更多的空間, 由於它須要兩個引用類型的標準配置:類型對象指針和同步塊索引spa

拆箱過程

int b = (int) o;
複製代碼
  1. 檢查引用類型是否爲null,不然拋出NullReferenceException異常。檢查對象實例,確保它是給定值類型的一個裝箱值。不然拋出InvaildCastException異常。
  2. 將該值的實例複製到值類型變量中。

與拆箱比較,裝箱的性能消耗更大,由於引用對象的分配更復雜,成本也就更高,值類型分配在堆棧上,分配和釋放的效率都很高。指針

相關文章
相關標籤/搜索