CLR via C 5 1 基元型別

2022-01-17 03:39:40 字數 3157 閱讀 7401

某些資料類在開發中非常常用,以至於許多編譯器允許**已簡化的語法來操作它們。例如可以使用以下語法來分配乙個整數:

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位值

intsystem.int32

yes有符號32位值

uint

system.uint32

no無符號32位值

long

system.int64

yes有符號64位值

ulong

system.uint64

no無符號64位值

char

system.char

yes16位unicode字元

float

system.single

yesieee32位浮點值

double

system.double

yesieee64位浮點值

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)); //ok

checked:

byte b = 100;

b = checked((byte)(n+200)); //丟擲溢位異常

c#還提供

checked和unchecked語句

checked

在visaul studio的"高階生成設定"對話方塊中可以指定編譯器是否檢查溢位。

system.decimal型別是乙個非常特殊的型別。雖然c#將decimal視為乙個基元型別,但clr則不然,也就是說clr沒有相應的il指令來決定如何處理decimal值。decimal值得處理速度是要慢於其他clr基元型別的值得處理速度。還有對decimal來說,checked和uncheked操作符、語句和編譯器都是無效的,decimal溢位時是一定會丟擲異常的。

CLR via C 5 1 基元型別

某些資料類在開發中非常常用,以至於許多編譯器允許 已簡化的語法來操作它們。例如可以使用以下語法來分配乙個整數 system.int32 a new system.int32 當然,你肯定不願意使用這種語法,c 允許使用如下所示的語法 int a 0 這種語法不僅增強 的可讀性,而且生成的il 和是有...

CLR via C 5 1 基元型別

原文 clr via c 5.1 基元型別 某些資料類在開發中非常常用,以至於許多編譯器允許 已簡化的語法來操作它們。例如可以使用以下語法來分配乙個整數 system.int32 a new system.int32 當然,你肯定不願意使用這種語法,c 允許使用如下所示的語法 int a 0 這種語...

CLR via C 第五章 程式語言的基元型別

基元型別的概念 編譯器直接支援的資料型別稱為基元型別。基元型別會直接對映到frameeork類庫中存在的型別。像這樣的沒有繼承關係的fcl型別之間的相互轉換。按理說是不能通過的 根據第四章型別物件的知識 但是這樣編寫實際上是不會出錯的。原因是編譯器非常熟悉基元型別,並在編譯 時應用他自己的特殊規則。...