1:JIT(即時編譯)。一個方法在第一次調用時JIT會把改方法的IL代碼轉換成CPU指令,再次調用該方法時就只需執行對應的指令。方法第一次被調用的過程大致是:1獲得方法的IL代碼;2:分配記憶體;3:將IL代碼轉換成CPU指令存在2分配的記憶體中;4:將方法表中對應該方法的指標指向2分配的記憶體;5:跳轉到2分配的記憶體執行其中的指令,即該方法的CPU指令。
2:as的效能高於is。Is的作用是判斷當前類型與目標類型是否相容,即是否是同一類型或者目標類型是當前類型的父類型。強制類型轉換也要判斷類型的相容性,如果不相容就拋出一個類型轉換異常,如果你的代碼類型轉換用Is+強制類型轉換就做了兩次相容性判斷,而as只有一次類型轉換。
3:C#中的int對應FCL中的Int32,long對應FCL中的Int64,同一類型,64位CPU所需儲存的空間是32位CPU的2倍。
4:string是參考型別,常量字串都存在字串池中,如果一個字串在代碼中多次出現,那麼這些都是對字串池的引用,string s="a"+"b";只分配了一次記憶體,編譯器會直接將其編譯成string s="ab";s是對字串池中ab的引用。
5:大量字串的拼接用StringBuilder,少量則用字串相加,能用+=則更好,string.format的效率是低下的,它的記憶體其實是params object[] +StringBuilder,params也是低效的,字串相加,或是取其中的一部分都是要重新分配記憶體,然後將對應的字串存入。FCL大部分代碼都是用C#寫的,而操作字串這一塊用的是Unmanaged 程式碼寫的,處於對效能的考慮。
6:別看到new就以為會在託管堆中分配記憶體,實值型別的變數就是分配中線程棧上的,結構體雖然可以用new,但是編譯器推斷出它是實值型別,就會按照實值型別的處理,當然IL代碼中是沒有newobj指令的。
7:靜態類被編譯成sealed abstract類型,所以他不能被繼承,不能被執行個體化,所以他的屬性和方法都是屬於類型的,沒有屬於對象的,它必須直接繼承Object。
8:const和readOnly的區別,IL代碼中存的是const變數的值,而不是引用,所以修改是不可能的,如果一個DLL只引用了另一個DLL中的一個const變數,那麼這個DLL是不會被引用的,因為編譯的時候就知道變數的值了,所以在啟動並執行時候也不會分配記憶體,readonly表示你不能修改它的指向,但是可以修改它所指向變數的值。
9:泛型,C#中的泛型和C++的模版區別在於參考型別,C++模版會每一種類型都會產生一個新的類型(參考型別是不會的),而C#泛型中,參考型別用的是同一個類型,只有實值型別用的是不同的類型。因為引用都是一個指標的引用,而實值型別儲存所需的空間是不同的。在C++中有模版半特化,將T 半特化成void*,這樣指標類型就不用再產生一套代碼了
其他基礎知識,請看這篇部落格:這些天寫的技術微博
作者:陳太漢
部落格:http://www.cnblogs.com/hlxs/