某些數據類在開發中非常常用,以至於許多編譯器允許代碼已簡化的語法來操作它們。例如可以使用以下語法來分配一個整數:
System.Int32 a = new System.Int32();
int a = 0;
基元類型(primitive type)。基元類型直接映射到Framework類庫(FCL)中存在的類型。比如以下4行代碼都是正確的,生成的IL代碼也是相同的。
int a = 0; System.Int32 a =0; int a = new int(); System.Int32 a = new System.Inte32();
下表列出了FCL類型在C#中對應的基元類型:
C#基元類型 FCL類型 CLS相容 說明 sbyte System.SBte NO 有符號8位值 byte System.Byte YES 無符號8位值 short System.Int16 YES 有符號16位值 ushort System.UInt16 NO 無符號16位值 int System.Int32 YES 有符號32位值 uint System.UInt32 NO 無符號32位值 long System.Int64 YES 有符號64位值 ulong System.UInt64 NO 無符號64位值 char System.Char YES 16為Unicode字符 float System.Single YES IEEE32位浮點值 double System.Double YES IEEE64位浮點值 bool System.Boolean YES 一個true/false值 decimal System.Decimal YES 一個128位高精度浮點值,常用於不容許捨入誤差的金融計算 string System.Strign YES 一個字符數組 object System.Object YES 所有類型的基類型 dynamic System.Object YES 對於CLR,dynamic和object完全一致。然而,C#編譯器允許使用一個簡單的語法,讓dynamic變量參與動態調度
可以想象C#編譯器自動假定在所有的源代碼文件中添加了以下using指令:
using sbyte = System.Sbyte; using byte = System.Byte; using int = System.Int32; using uint = System.UInt32; ......
C#語言規范上說:"從風格上上,最好使用關鍵字,而不是使用完整的系統類型名稱"。但本書作者並不同意這種說法,以下是他的一些理由:
1)很多開發人員困惑於應該使用string還是String。由於C#的string(關鍵字)是直接映射到System.String(一個FCL類型),所以兩者是沒有區別的。還有開發人員認為,在32位系統中int是32位整數,在64位系統中就變成64位整數了,事實並不是這樣。在C#中,int始終映射到System.Inte32,所有不管什麼系統,int都是32位整數,如果都使用Int32就不會產生這種誤解。
2)在C#中,long映射到System.Int64,當在其他編程語言中,long可能映射到的是Int16或Int32。這樣在看別的編程語言時容易產生誤解。
BinaryReader br =new BinaryReader(...); float val = br.ReadSingle(); //正確,當看上去不自然 Single val = br.ReadSingle(); //正確,看上去一目了然4)平時只用C#的許多程序員逐漸淡忘了還可以使用其他語言寫面向CLR的代碼。因此造成了"C#主義"入侵類庫代碼。 對基元類型執行許多算數運算都可能造成溢出。不同語言處理溢出也是不同的。C和C++不將溢出視為錯誤,並允許值回滾;應用程序"若無其事"的運行著。相反,Microdsoft Visual Basic總是將溢出視為錯誤,並會拋出異常。 CLR提供了一些特殊的IL指令,允許編譯器選擇它認為最恰當的行為。CLR有一個add指令,將兩值相加但不檢查溢出。還有一個add.ovf指令,作用是兩值相加,溢出時拋出異常。類似的還有sub/sub.ovf等。 C#允許開發人員自己決定如何處理溢出。溢出檢查默認是關閉的。開發人員可以使用C#編譯器控制溢出的一個辦法是使用/checked+編譯器開關。 C#通過提供checked和unchecked操作符來實現局部是否檢查發生溢出。
unchecked: UInt32 invalid = unchecked((UInt32)(-1)); //OK checked: Byte b = 100; b = checked((Byte)(n+200)); //拋出溢出異常
checked{ Byte b = 100; b = checked((Byte)(n+200)); }
在Visaul Studio的"高級生成設置"對話框中可以指定編譯器是否檢查溢出。
System.Decimal類型是一個非常特殊的類型。雖然C#將Decimal視為一個基元類型,但CLR則不然,也就是說CLR沒有相應的IL指令來決定如何處理Decimal值。Decimal值得處理速度是要慢於其他CLR基元類型的值得處理速度。還有對Decimal來說,checked和uncheked操作符、語句和編譯器都是無效的,Decimal溢出時是一定會拋出異常的。