某些數據類在開發中非常常用,以至于許多編譯器允許代碼已簡化的語法來操作它們。例如可以使用以下語法來分配一個整數:
System.Int32 a = new System.Int32();
當然,你肯定不愿意使用這種語法,C#允許使用如下所示的語法:
int a = 0;
這種語法不僅增強代碼的可讀性,而且生成的IL代碼和是有System.Int32時生成的IL代碼是完全一致的。
編譯器直接支持的數據類型稱為基元類型(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.SByte | 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.String | 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。這樣在看別的編程語言時容易產生誤解。
3)FCL的許多方法都將類型名稱作為方法名的一部分。
BinaryReader br =new BinaryReader(...); float val = br.ReadSingle(); //正確,當看上去不自然 Single val = br.ReadSingle(); //正確,看上去一目了然4)平時只用C#的許多程序員逐漸淡忘了還可以使用其他語言寫面向CLR的代碼。因此造成了"C#主義"入侵類庫代碼。 對基元類型執行許多算數運算都可能造成溢出。不同語言處理溢出也是不同的。C和C++不將溢出視為錯誤,并允許值回滾;應用程序"若無其事"的運行著。相反,Microsoft Visual Basic總是將溢出視為錯誤,并會拋出異常。 CLR提供了一些特殊的IL指令,允許編譯器選擇它認為最恰當的行為。CLR有一個add指令,將兩值相加但不檢查溢出。還有一個add.ovf指令,作用是兩值相加,溢出時拋出異常。類似的還有sub/sub.ovf等。 C#允許開發人員自己決定如何處理溢出。溢出檢查默認是關閉的。開發人員可以使用C#編譯器控制溢出的一個辦法是使用/checked+編譯器開關。 C#通過提供checked和unchecked操作符來實現局部是否檢查發生溢出。
unchecked:UInt32 invalid = unchecked((UInt32)(-1)); //OKchecked:Byte b = 100;b = checked((Byte)(n+200)); //拋出溢出異常
C#還提供checked和unchecked語句
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溢出時是一定會拋出異常的。
新聞熱點
疑難解答