C#中的基元類型
這篇文章我想複習下C#中的基元類型。雖然搞清楚基元類型的知識並不會是你工作的必要條件,但做為一個搞技術的人來說還是非常有必要的。起碼可以對付有些顯得比較BT的面試題,哈哈!
關於什麼是基元類型,我想並不是每一位開發人員都清楚的,有部分的朋友只知道怎麼在工作中應用它(例如int,string)。如果一個編程基礎比較紮實的朋友來說當然不在話下,就不說別人,拿我自己來說,編程三年多,我都不太關心什麼是基元類型,它有什麼用,其實不知道這些對工作也不會產生決定性的影響。如果你不知道基底類型的概念,但會用int,float之類,對平常工作是沒有太大影響的。但如果有人和你討論這些東西時,還是覺的非常有必要對其進行瞭解和學習。
比較常見的問題,其中一個也是最近園友說過的:
第一:int和int32有啥區別?
第二:string和String又有啥區別?
像很多園友回複的一樣,對這些東西有時不必要太過較真,但既然有這樣的問題,總規要有答案了。這裡我列出以下幾種申明一個整形變數的代碼:
//最簡單
int a = 0;
//較簡潔的
Int32 b=0;
//不簡潔的
int c = new int();
//最不簡潔
System.Int32 d = new System.Int32();
我們再來看下這些代碼產生的IL代碼:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代碼大小 10 (0xa)
.maxstack 1
.locals init ([0] int32 a,
[1] int32 b,
[2] int32 c,
[3] int32 d)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: ldc.i4.0
IL_0004: stloc.1
IL_0005: ldc.i4.0
IL_0006: stloc.2
IL_0007: ldc.i4.0
IL_0008: stloc.3
IL_0009: ret
} // end of method Program::Main
結論:它們都是申明一個int32類型的變數,並且對其進行了初始化。至於這是什麼原因呢?這裡就只能用基元類型來解釋了。我們來看下C#的基元類型和FCL以及CLS的部分關係。從下面的表中可以看出:
C# Primitive Typ |
FCL Type |
CLS-Compliant |
sbyte |
System.SBte |
NO |
byte |
System.Byte |
YES |
short |
System.Int16 |
YES |
ushort |
System.UInt16 |
NO |
int |
System.Int32 |
YES |
uint |
System.UInt32 |
NO |
long |
System.Int64 |
YES |
ulong |
System.UInt64 |
NO |
char |
System.Char |
YES |
float |
System.Single |
YES |
double |
System.Double |
YES |
decimal |
System.Decimal |
YES |
object |
System.Object |
YES |
string |
System.Strign |
YES |
1:int被映射到FCL中的System.Int32中。這裡足以解釋上面四種建立變數的結果為什麼是一樣的原因。
2:string和System.Sting其實並無實質的區別,說的簡單點,string是String的一個別名。
using方式理解基元類型和FCL的關係 : 可以利用using語句來實現:
using sbyte=System.SBYTE;
using int=System.Int32;
using string=System.String;
FCL類型之間的轉換:我們知道在FCL類型變數之間可以進行相關的轉換,例如:
Int32 i=0;
Int64 j=i;//隱式轉換成Int64
下面是對應的IL代碼:我們可以看出有一人conv.i8操作,這裡就是資料類型的轉換。
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// 代碼大小 7 (0x7)
.maxstack 1
.locals init ([0] int32 i,
[1] int64 j)
IL_0000: nop
IL_0001: ldc.i4.0
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: conv.i8
IL_0005: stloc.1
IL_0006: ret
} // end of method Program::Main
分析:從OO的角度來講,這種轉換並不是"太正常":
1:Int32和Int64是兩種不同的資料類型;
2:兩者之間並不存在繼承關係。
問題:為什麼兩者之間能夠正常轉換呢?也是因為基元類型和的關係。
類型之間的轉換提供了兩種方式:
第一:隱式轉換,如果兩個類型之間是型別安全的,則可以直接進行轉換;
第二:顯示轉換,類型之間是非安全的,需要強制轉換。