這兩章全是理論性的東西,我覺得不必過於鑽牛角尖。理論這東西,只有在長期的實踐中去慢慢領悟才會深刻。下面我只寫些我認為重要的關鍵知識。
(一)型別轉換
知識點:向基型別的轉換被認為是一種安全的隱式轉換;向派生型別轉換時,只能顯示轉換。
舉例:
Object o = new Employee(); Employee e = (Employee)o;
重要認知:CLR的型別檢查會遍歷繼承層次結構,用每個基型別去核對指定的型別。
常用程式碼:(見下方程式碼段。CLR會檢查兩次物件的型別):
if(o is Employee){ Employee e = (Employee)o; }
簡化程式碼:(見下方程式碼段。CLR會檢查一次物件的型別)
Employee e = o as Employee; if(e != null){ //... }
(二)值型別和引用型別
重要認知:1.棧中儲存的是值型別、引用型別的指標(地址);堆中儲存引用型別本身(不全是,見2)。
2.包含在引用型別內的值型別不會被儲存在棧中,而是堆中(還是值型別,未被裝箱),它被包含於引用型別物件中。
(三)重視裝箱和拆箱對程式效能的影響
理解以下程式碼中的三次裝箱:
public static void Main(){ Int32 v=5; Object o =v; v=123; Console.WriteLine(v + ", " + (Int32)o ); }
第一次裝箱是將v轉換成object物件;第二次和第三次是因為WriteLine()方法要獲取一個String物件,這樣v和被拆箱的o會被再次裝箱。
“裝箱”發生的事情:
1. 在託管堆中分配記憶體,包括值型別欄位需要的記憶體量+型別物件指標的記憶體量+同步塊索引需要的記憶體量。
2. 值型別的欄位複製到新分配的堆記憶體。
3. 返回物件的地址。(地址是對物件的引用(指標),值型別變成引用型別)
概念應用:
重寫類中的ToString()方法,可以避免使用ToString()方法時的裝箱問題。
public class A { private int x; public override String ToString() { return string.formart("{0}",x); } }
注意重寫的ToString()方法內部如果呼叫了base.ToString();外部呼叫此方法時,值型別依然會被裝箱。