類別外傳(1) Type Object

  • 1872
  • 0
  • OOP
  • 2016-01-31

好一陣子沒寫文章了, 來寫點關於類別的故事好了. 為什麼題目不叫型別外傳而叫類別外傳呢 ? 因為這樣就可以排除掉列舉和結構型別, 簡單說就是懶啦. 這系列不打算講甚麼類別是參考型別這類的問題, 因為這個議題很多人討論過了, 我想要討論一些比較無趣的課題.

        好一陣子沒寫文章了, 來寫點關於類別的故事好了. 為什麼題目不叫型別外傳而叫類別外傳呢 ? 因為這樣就可以排除掉列舉和結構型別, 簡單說就是懶啦. 這系列不打算講甚麼類別是參考型別這類的問題, 因為這個議題很多人討論過了, 我想要討論一些比較無趣的課題.

 

 

        想寫這篇文的原因來自於我常常問的一個問題 : 『類別本身在記憶體裡面會不會形成一個物件 ? (我所指的是類別本身, 而不是呼叫 new 由此類別產生的執行個體)』.  有很大的機率會得到 『不會』這個答案, 但事實上的答案是『會的』. 當你使用到某個類別的時候, 在記憶體中會為這個類別產生一個型別物件, 這個型別物件的型別就是 Type Class (試著快速念三遍…).

 

 

        對於型別物件有兩個特性 (1) 當你使用到該型別時, CLR 會幫你產生型別物件 (2) 每一種型別的型別物件在該 AppDomain 只會被產生一次, 也就是在記憶體中僅會有一份. 試著先記住這兩件事, 後面我會證明這兩個特性.

 

 

        型別物件的存在

        其實要證明型別物件存在很簡單, C# 有個 typeof() 運算式, Object 有個方法叫 GetType(), 這兩個方法回傳的型別是甚麼 ? 就是 System.Type, 意即這兩個方法回傳的值就是指向該型別的型別物件. 既然你可以用變數存取它, 表示它必然以某種物件的形式存在於記憶體. 否則你如何存取 ?

 

 

        記憶體中只會存在一份該型別的型別物件

        要證明這件事, 只要用上 Object.ReferenceEquals 方法就可以證明了, 這個方法比較的是兩個變數所指向的物件是不是位在同一個位址上, 所以簡單的程式碼就可以證明獨一的論述.

   1: namespace ConsoleApplication1
   2: {
   3:     class Program
   4:     {
   5:         static void Main(string[] args)
   6:         {
   7:             Type t1 = typeof(Class1);
   8:             Class1 c = new Class1();
   9:             Type t2 = c.GetType();
  10:             Console.WriteLine(Object.ReferenceEquals(t1, t2));
  11:             Console.ReadLine();
  12:         }
  13:     }
  14:  
  15:     public class Class1
  16:     {
  17:         public string str;
  18:         public Class1()
  19:         {
  20:  
  21:         }
  22:     }
  23: }

 

        這個答案是 True, 也就是 t1, t2 指向的物件是同一個. 這篇先就此打住, 下回來談點別的.