有時候,咱們不想用值類型的值,就是想用一個引用。.Net提供了一個名爲裝箱(boxing)的機制,它容許根據值類型來建立一個對象,而後使用對這個新對象的一個引用。express
首先,回顧兩個重要的事實,1.對於引用 類型的變量,它的值永遠是一個引用;2.對於值類型的變量,它的值永遠是該值類型的一個值。性能
int i = 5; object o = i; int j = (int)o;
這裏有兩個變量:i是值類型的變量,o是引用類型的變量。將i的值賦給o有道理嗎?o的值必須是一個引用,而數字5不是一個引用,它使用整數值。實際發生的事情就是裝箱:運行時將在堆上建立一個包含值(5)的對象,o的值是對該新對象的一個引用。該對象的值是原始值的一個副本,改變i的值不會改變箱內的值。spa
第3行執行相反的操做——拆箱。必須告訴編譯器將object拆箱成什麼類型。若是使用了錯誤的類型(好比o原先被裝箱成unit或者long,或者根本就不是一個已裝箱的值),就會拋出一個InvalidCastException異常。一樣,拆箱也會複製箱內的值,在賦值以後,j和該對象之間再也不有任何關係。code
剩下的惟一問題就是要知道裝箱和拆箱在何時發生。拆箱通常很明細的,由於要在代碼中明確地顯示一個強制類型轉換。裝箱則可能在沒有意識的時候發生。如上面代碼的第二行。可是,爲了一個類型的值調用ToString,Equals或GetHashCode方法時,若是該類型沒有覆蓋這些方法,也會發生裝箱。(同時,當你調用類型變量值的GetType()方法時,也會伴隨着裝箱的過程。若是處理爲裝箱形式的變量,你應該已經知道了具體類型,所以使用typeof替代便可。)別外,將值做爲接口表達式使用時——把它賦值給一個接口類型的變量,或者把它做爲接口類型的參數來傳遞——也會發生裝箱。例如,Icomparable x = 5;語句會對5進行裝箱。對象
之因此要留意裝箱和拆箱,是因爲它們可能會下降性能。一樣這種性能損失一般不是大問題,可是仍是應該值得注意。接口
針對typeof,getType is as 的一些代碼ci
public class Animal { } public class Dog : Animal { }
/// <summary> /// typeof takes a type name(which yoy specify at compile time) /// GetType gets the runtime type of an instance /// is returns true if an instance is in the inheritance tree /// </summary> public void TestTypeOfAndGetType() { var dog = new Dog(); var result = dog.GetType() == typeof(Animal); var result1 = dog is Animal; var result2 = dog.GetType() == typeof(Dog); Console.WriteLine("dog.GetType() == typeof(Animal) :{0}",result); Console.WriteLine("dog is Animal :{0}", result); Console.WriteLine("dog.GetType() == typeof(Dog):{0}", result); }
別外,關於as的,as運算符相似於強制轉換類型操做,可是,所以,若是轉換是不可能的,as返回null而不引起異常。下面兩句代碼是等效的:
expression as type
expression is type ? (type)expression : (type)null
下面是MSDN中的一個DEMO:
class ClassA { } class ClassB { } class MainClass { static void Main() { object[] objArray = new object[6]; objArray[0] = new ClassA(); objArray[1] = new ClassB(); objArray[2] = "hello"; objArray[3] = 123; objArray[4] = 123.4; objArray[5] = null; for (int i = 0; i < objArray.Length; ++i) { string s = objArray[i] as string; Console.Write("{0}:", i); if (s != null) { Console.WriteLine("'" + s + "'"); } else { Console.WriteLine("not a string"); } } } }
/* Output: 0:not a string 1:not a string 2:'hello' 3:not a string 4:not a string 5:not a string */