標籤:style blog color 使用 os 資料
I. C#中實值型別和參考型別
1. 類class 參考型別,結構struct實值型別
2. 數組是參考型別,即使元素是實值型別,int[]是參考型別
3. 枚舉是實值型別enum
4. 委託類型delegate是參考型別
5. 介面類型interface是參考型別,但可以由實值型別實現。
II. 值的運算式:運算式“2+3”的值就是5;而對於參考型別的運算式,它的值是一個引用,而不是該引用所指代的對象,如String.Empty的值不是一個Null 字元串,而是對Null 字元串的一個引用。
III. 變數的值在它聲明的位置儲存,局部變數的值總是存在棧stack中,引用對象的執行個體總是存放在堆heap中,靜態變數也是。
V. 實值型別不能派生出其他類型,不需要額外的資訊描述值實際是什麼類型;而參考型別,每個對象的開頭有一個標識對象實際類型的資料區塊,同時還提供一些其他資訊。永遠都不能改變對象的類型,執行簡單的強制類型轉換時,運行時擷取一個引用,檢查它引用的對象是否為目標類型的一個有效對象,若有效返回原始引用,否則拋出異常。
誤解:
誤區1:結構是輕量級的類
誤區2:參考型別儲存在堆上,實值型別儲存在棧上
引用的執行個體總是在堆上建立無誤。但是一個類中有一個int的執行個體變數,那個在類的任何對象中,該變數的值總是和對象的其他資料在一起,也就是在堆上。只有局部變數(方法內部聲明的變數)和方法的參數在棧上。對於C#2.0及以上,很多局部變數並無完全存放在棧中,詳見後續匿名方法。
誤區3:對象在C#中預設是通過引用傳遞的:參考型別作為方法參數傳遞時,預設是使用“值傳遞”--這個值是一個引用。
VI. 拆箱和裝箱
對於參考型別的變數,它的值永遠是一個引用;對於實值型別的變數,它的值永遠是該實值型別的一個值。
int i=5;object o=i;int j= (int)o;
i是實值型別的變數,o是參考型別的變數。將i賦值給o,發生裝箱:運行時將在堆上建立一個包含值(5)的對象。o的值是該對象的一個引用,該對象的值是原始值的一個副本,改變i的值對該對象的值無影響。
拆箱:o被拆箱成int 類型的值,拆箱無誤(即o的值可以轉化為int),複製箱內的值給j,拆箱後j和該對象沒有任何關係。
拆箱很容易看出來,有強制的類型轉化。什麼時候會裝箱呢?裝箱比較隱蔽,通常為一個實值型別調用ToString,Equals或GetHashCode方法是,該類型沒有覆蓋這些方法時,會裝箱。GetType()不能被重載,實值型別調用時會裝箱,所以可以是有typeof代替。另外將一個實值型別賦給介面的變數時,也會裝箱,如IComparable x =5;