CLR VIA C#教程之基元類型 值類型 引用類型介紹
我很喜歡《CLR Via C#》這本書,但一直都沒能深入理解,而且很多內(nèi)容也忘記了,現(xiàn)在準(zhǔn)備重新看一遍,并將看過的部分寫出來,因為寫的過程也是一個加深理解的過程。本系列算是學(xué)習(xí)的一個記錄吧,也可以方便以后自己查閱,如果對大家還有些幫助的話,我就很高興了。書我是選擇性的看的,所以順序和書中的順序可能不一樣。
首先了解下什么是基元類型,基元類型是編譯器直接支持的數(shù)據(jù)類型,像我們平時經(jīng)常用到的int string bool 都是基元類型,基元類型是映射到FCL中的類型,像前面的三種類型對應(yīng)到FCL中就是Int32 String Boolean,基元類型只是給我們的編程提供了方便,它和FCL中的類型在編譯后最終生成的IL完全相同。下面給出基元類型和FCL類型的對應(yīng)表
我們平時在寫程序時通常都是使用基元類型,因為方便,但本書的作者認(rèn)為應(yīng)該直接使用FCL中的類型,原因如下:
C#基元類型 |
FCL類型 |
CLS相容 |
說明 |
sbyte |
System.Sbyte |
|
|
byte |
System.Byte |
|
|
short |
System.Int16 |
|
|
ushort |
System.UInt16 |
|
|
int |
System.Int32 |
|
|
uint |
System.Uint32 |
|
|
long |
System.Int64 |
|
|
ulong |
System.Uint64 |
|
|
char |
System.Char |
|
|
float |
System.Single |
|
|
double |
System.Double |
|
|
bool |
System.Boolean |
|
|
decimal |
System.Decimal |
|
|
object |
System.Object |
|
|
string |
System.String |
|
|
在c#中l(wèi)ong對應(yīng)的FCL類型為System.Int64,但是在其他的語言中,如c++ 就將long視為一個Int32。這樣習(xí)慣于一種編程語言的人在看另一種編程語言寫的源碼是就會產(chǎn)生錯誤的理解。在FCL中的許多的方法將類型名作為方法名的一部分,如System.Convert類提供ToBoolean,ToInt32,ToSingle等。這樣在使用基元類型做類型轉(zhuǎn)換時就感覺有點怪怪的,如:float val=Convert.ToSingle(“23”);
CLR VIA C#教程之值類型和引用類型的區(qū)別
1.所有的值類型都是從System.TypeValue派生,如Struct Enum都是值類型;所有引用類型都是從System.Object派生。
2.值類型分配在線程堆棧上,引用類型分配在托管堆上。
3.值類型表現(xiàn)形式有未裝箱形式和已裝箱形式,而引用類型總是已裝箱形式。
4.所有的值類型都是sealed類型,所以值類型不能作為任何類型的基類型,也不能在值類型中引入虛方法。
5.創(chuàng)建一個引用類型變量時,會被初始化為null,試圖使用一個null的引用類型變量時,會拋出NullReferenceException異常,也就是常見的“未將對象引用設(shè)置到對象的實例”;值類型在創(chuàng)建時所有成員都初始化為0了,所以不會拋出該異常。
原文例子表示值類型和引用類型的區(qū)別
- class Program
- {
- static void Main(string[] args)
- {
- SomeRef r1 = new SomeRef();
- SomeVal v1 = new SomeVal();
- r1.x = 5;
- v1.x = 5;
- Console.WriteLine(r1.x); //5
- Console.WriteLine(v1.x); //5
- SomeRef r2 = r1;
- SomeVal v2 = v1;
- r1.x = 8;
- v1.x = 9;
- Console.WriteLine(r1.x); //8
- Console.WriteLine(r2.x); //9
- Console.WriteLine(v1.x); //9
- Console.WriteLine(v2.x); //5
- }
- }
- class SomeRef
- {
- public Int32 x;
- }
- struct SomeVal
- {
- public Int32 x;
- }
CLR VIA C#教程之CLR中類型字段布局的控制
為了提高性能,clr能按照所選擇的任何方式來排列類型的字段。我們可以通過在類會是結(jié)構(gòu)上使用System.Runtime.InteropServices.StructLayoutAttribute屬性來改變這種排列的順序。該屬性接受一個LayoutKind的枚舉值(Auto,Sequential,Explicit),默認(rèn)情況下C#編譯器會為類選擇Atuo,為結(jié)構(gòu)選擇Sequential。下面來定義一個類和一個結(jié)構(gòu)
- struct SomeVal
- {
- public String name;
- public Int32 id;
- }
- class SomeRel
- {
- public String name;
- public Int32 id;
- }
查看IL代碼可以看到默認(rèn)的排列順序
現(xiàn)在給類和結(jié)構(gòu)加上屬性,首引用加命名空間 using System.Runtime.InteropServices;
- [StructLayout(LayoutKind.Auto)]
- struct SomeVal
- {
- public String name;
- public Int32 id;
- }
- [StructLayout(LayoutKind.Sequential)]
- class SomeRel
- {
- public String name;
- public Int32 id;
- }
再查看IL可以看到順序已經(jīng)發(fā)生了變化
C#編譯器總是會默認(rèn)給結(jié)構(gòu)這樣的值類型選擇Sequential,是因為值類型會經(jīng)常和非托管代碼進(jìn)行交互,字段必須保持和開發(fā)人員定義的一致。我們在編碼過程中如果判斷所創(chuàng)建的值類型不會與非托管代碼進(jìn)行交互,就可以像上面那樣給創(chuàng)建的值類型添加[StructLayout(LayoutKind.Auto)] ,讓其進(jìn)行自動排列,以提高性能。
查看IL代碼可以看到默認(rèn)的排列順序,以上是CLR VIA C#教程系列之一。
【編輯推薦】