《CLR.via.C#第三版》第二部分第4,5章節讀書筆記(二)

杭偉發表於2014-11-07

這兩章全是理論性的東西,我覺得不必過於鑽牛角尖。理論這東西,只有在長期的實踐中去慢慢領悟才會深刻。下面我只寫些我認為重要的關鍵知識。

(一)型別轉換

知識點:向基型別的轉換被認為是一種安全的隱式轉換;向派生型別轉換時,只能顯示轉換。

舉例:

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();外部呼叫此方法時,值型別依然會被裝箱。

相關文章