初學者可能很少聽說過這個名詞,但是平時用得最多的肯定是基元類型。先看下面兩行代碼:
System.Int32 a = 5; int a = 5;
上面兩行代碼都表示聲明一個int類型的變量,但在平時寫代碼的時候我們一般用的是第二種方式。第二種方式不僅簡潔、易讀,而且生成的IL代碼和第一種完全一致。像這種編譯器直接支持的數據類型就稱為基元類型。類似的還有double、bool、long、string等。
在我接觸的第一份面試題中,我記得有這麼一道題目:請談談C#中string和String的區別?
我當時確實懵逼了,有區別嗎?好像用的時候完全沒有區別。其實二者說有區別也可以,說沒區別也沒錯。因為基元類型sting直接映射到FCL中的String類型。所以本質上他倆是同一個東西。
在C#中,基元類型都直接映射到.NET框架類庫中存在的類型。之前看了一本書,關於這種映射有一種解釋:
using string = System.String;
從這個角度可以認為,C#編譯器假定所有源文件都添加了using指令。
下面列舉C#基元類型在FCL中對應的類型:
C#基元類型 FCL類型 符合CLS 說明 sbyte System.SByte 否 有符號8位整數 byte System.Byte 是 無符號8位整數 short System.Int16 是 有符號16為整數 ushort System.UInt16 否 無符號16位整數 int System.Int32 是 有符號32位整數 uint System.UInt32 否 無符號32位整數 long System.Int64 是 有符號64位整數 ulong System.UInt64 否 無符號64位整數 char System.Char 是 16位Unicode字符 float System.Single 是 32位浮點數 double System.Double 是 64位浮點數 bool System.Boolean 是 true/false值 string System.String 是 字符數組 object System.Object 是 所有類型的基類型
FCL中只要符合公共語言規范(CLS)的類型,其他語言都提供了類似的基元類型,但是不符合CLS的類型,其他語言就不一定支持了。
C#編譯器支持與類型轉換、字面值以及操作符有關的模式。
首先,編譯器能執行基元類型之間的隱式或顯示轉換,例如:
int a = 5; //從Int32隱式轉換為Int32 long b = a; //從Int32隱式轉換為Int64 byte d = (byte)a; //從Int32顯示轉換為Byte short e = (short)a; //從Int32顯示轉換為Int16
System.Int64與System.Int32是不同的類型,而且不存在派生關系。那麼他們之間為什麼能隱式轉換呢?原因是C#編譯器非常熟悉基元類型,會在編譯代碼時應用自己的特殊規則。也就是說,編譯器能識別常見的編程模式。
但是,只有在轉換安全的情況下,C#才允許隱式轉換。所謂的安全是指不會發生數據丟失的情況。比如Int32轉換為Int64。但如果可能不安全,C#就要求顯示轉換。對於數值類型,不安全意味著轉換後可能丟失精度或數量級。例如Int32轉Byte,Int32表示有符號32位二進制數,最大值為:2^16-1,而Byte表示無符號8位二進制數,最大值為:2^8-1,所以大的Int32可能丟失精度。
除了轉型,基元類型還能寫成字面值。字面值可以堪稱基元類型本身的實例。所以可以調用實例方法,例如:
string a = 123.ToString(); //Int32實例123調用ToString()方法
此外,如果表達式由字面值構成,編譯器在編譯時就能完成表達式求值,例如:
int a = 100+20+3; //生成的代碼將a的值設為123 string b = "a"+"bc"; //生成的代碼將b的值設為“abc”
最後,編譯器知道如何和以什麼順序解析代碼中的基元類型和操作符之間的運算,例如:
int a = 5; //賦值操作 int b = a + 10; //加和賦值操作 bool c = (a<0); //小於和賦值操作
參考文獻:CLR via C#(第四版)
PS:新手正在學習.NET Framework,有什麼錯誤希望各位指正!