从C#2.0的角度看.NET 2.0类型系统
生活随笔
收集整理的這篇文章主要介紹了
从C#2.0的角度看.NET 2.0类型系统
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
C#中所有變量使用之前都必須初始化,否則編譯器會(huì)在初始化時(shí)產(chǎn)生一個(gè)編譯錯(cuò)誤。
每個(gè)Windows線程都有一個(gè)私有的內(nèi)存區(qū)塊,稱為棧;也就是說(shuō)這塊內(nèi)存塊不能被其他線程訪問(wèn)(特定條件下除外)。什么條件?
線程的棧主要用于:
堆的優(yōu)點(diǎn)是容量比棧大得多。為所有線程所共享。
棧的優(yōu)點(diǎn)是速度比堆快。這主要源于專門(mén)訪問(wèn)棧的IL指令,以及訪問(wèn)棧上的元素?zé)o需同步。
因此,用堆來(lái)存儲(chǔ)大對(duì)象,用棧存儲(chǔ)小對(duì)象。。
C#中的值類型的實(shí)例使用靜態(tài)分配(分配在線程棧上),而引用類型的實(shí)例則使用動(dòng)態(tài)分配(分配在進(jìn)程堆中)。
結(jié)構(gòu)、枚舉是值類型,委托是引用類型
如果某個(gè)類的實(shí)例有個(gè)值類型的字段,那么該字段會(huì)和類實(shí)例保存在一起,即堆中。反過(guò)來(lái),如果一個(gè)結(jié)構(gòu)的字段是引用類型,那么引用類型的實(shí)例還是會(huì)保存在堆中。
在C#中,求模運(yùn)算也可以用于浮點(diǎn)數(shù)。
float a = 5.5f;
Console.WriteLine(a % 2.5);
屏幕上將輸出0.5。
C#語(yǔ)言提供了checked關(guān)鍵字,可以得到驗(yàn)證所有的類型轉(zhuǎn)換和運(yùn)算。如果有問(wèn)題就會(huì)引發(fā)一個(gè)異常。
整形和decimal類型被零除時(shí),會(huì)產(chǎn)生DivideByZeroException異常。
浮點(diǎn)型float和double被零除時(shí),會(huì)得到無(wú)窮大,0/0得到Nan。
C#的遞增和遞減運(yùn)算符也可以用于浮點(diǎn)數(shù)。
float a = 5.5f;
a++;
此時(shí)a = 6.5。
C#中的結(jié)構(gòu)不能從其他類或者結(jié)構(gòu)派生,也不能作為其他類型或結(jié)構(gòu)的基類。
C#的結(jié)構(gòu)可以有多個(gè)構(gòu)造函數(shù),當(dāng)不允許自定義默認(rèn)的構(gòu)造函數(shù)(即沒(méi)有參數(shù)的構(gòu)造函數(shù))。而且編譯器要求每一個(gè)構(gòu)造函數(shù)都初始化結(jié)構(gòu)的所有字段。
默認(rèn)構(gòu)造函數(shù)將所有值類型的字段設(shè)為零,而將所有引用類型的字段設(shè)為空引用。
結(jié)構(gòu)可以有自己的方法。
與類的字段不同,結(jié)構(gòu)的字段不能在聲明中顯示初始化。
結(jié)構(gòu)的實(shí)例常常存儲(chǔ)在棧中,因此結(jié)構(gòu)不宜太大。太大的結(jié)構(gòu)最好用類代替。
編譯器默認(rèn)情況下,將枚舉的值視為int型整數(shù)。因此,枚舉定義的這組常數(shù)中任意一個(gè)值都是一個(gè)整數(shù)。可以對(duì)其進(jìn)行遞增、遞減操作。
在默認(rèn)情況下,枚舉的第一個(gè)值是0,之后的每一個(gè)值都是前一個(gè)值加1.當(dāng)然,也可以手工指定自己想要的值。
你也可以定義其他類型的枚舉類型的值:
??? enum MakerCHB:byte{Beijing,Zhejiang}
??? enum MakerCHL:long{Beijing,Zhejiang}
可以讓一個(gè)枚舉的實(shí)例包含多個(gè)枚舉值。這個(gè)概念也稱為二進(jìn)制位標(biāo)志(binary flag)或者標(biāo)志枚舉(flag enum).
注意,位域枚舉都打上了System.Flags attribute標(biāo)志,該attribute通知CLR和客戶端這個(gè)枚舉用來(lái)表示位域而不是標(biāo)準(zhǔn)枚舉,這個(gè)枚舉用來(lái)表示位域而不是標(biāo)準(zhǔn)枚舉。這個(gè)標(biāo)志會(huì)影響ToString()方法的結(jié)果。最好能有個(gè)實(shí)例!
.NET Framework中的System.Threading.ThreadState就是采用了二進(jìn)制標(biāo)志的枚舉。
C#中String類的實(shí)例是不可變。即無(wú)法修改它們,它們將保持通過(guò)構(gòu)造函數(shù)所賦的值不變。
C#允許定義無(wú)轉(zhuǎn)義的字符串字面常量,方法就是在字符串起始的雙引號(hào)之前加入“@”符號(hào)。無(wú)轉(zhuǎn)義字符串字面常量具有以下特征:
通過(guò)不安全代碼也可以打破字符串實(shí)例的不可變特性。
C#允許用delegate關(guān)鍵字創(chuàng)建一種特殊的類,我們稱這種類為委托類。委托類的實(shí)例稱為委托對(duì)象。
委托對(duì)象是一種指向一個(gè)或多個(gè)方法(靜態(tài)或非靜態(tài))的引用。我們可以像調(diào)用方法那樣“調(diào)用”委托對(duì)象,這其實(shí)就是調(diào)用委托對(duì)象所引用的方法。注意這些方法的調(diào)用是在調(diào)用委托的方法所在的線程中完成的,即同步調(diào)用。
委托變量所能引用的方法只能是其簽名式與委托類聲明中所提供的簽名式一致的方法。
delegate?void?Deleg1();
delegate?string?Deleg2(string?s);
delegate?void?f1()
{
}
static?string?f2(string?s)
{
}
Deleg1?d1?=?new?Deleg1(f1);???//?right
Deleg2?d2?=?new?Deleg2(f2);???//?right
Deleg2?d3?=?new?Deleg2(f1);???//?error C# 2.0編譯器引入在創(chuàng)建委托變量時(shí)推測(cè)其類型的功能。于是就可以直接將一個(gè)方法賦給隱式創(chuàng)建的對(duì)象。如
Deleg1 d1 = f1;
Deleg2 d2 = f2;
但是,其編譯生成的IL代碼,跟前面的是一樣的,它仍舊調(diào)用了Deleg1和Deleg2委托類的構(gòu)造函數(shù)。
可以用一個(gè)委托對(duì)象應(yīng)用多個(gè)具有相同簽名式的方法(靜態(tài)或非靜態(tài))。這種情況下調(diào)用委托對(duì)象就會(huì)在調(diào)用對(duì)象的線程中順序執(zhí)行所有的方法。調(diào)用方法的順序就是方法添加到委托對(duì)象中的順序,每個(gè)方法的參數(shù)都是一樣的。
如果委托的簽名具有返回值,那么引用多個(gè)方法時(shí)只有最后一個(gè)調(diào)用的方法的返回值才作為委托對(duì)象的返回值返回。
可以用GetInvocationList()獲取該委托對(duì)象中的委托列表。
可空類型System.Nullable<T>等價(jià)于T?。
??? 即int? i = null;和Nullable<int> i = null;是等價(jià)的。
不過(guò),編譯器會(huì)阻止從可空類型到原始類型的隱式轉(zhuǎn)換。此外,不事先測(cè)試而進(jìn)行可空類型到原始類型的顯示轉(zhuǎn)換也是危險(xiǎn)的,因?yàn)?#xff0c;這可能會(huì)引發(fā)InvalidOperationException異常。
C# 2.0允許將類、結(jié)構(gòu)和接口的聲明分散到多個(gè)源文件中。我們稱這一特性命名為部分類型。注意,委托類或者枚舉類是不能聲明在多個(gè)源文件中的。
同一個(gè)類型各個(gè)不同的部分定義前面必須都加partial關(guān)鍵字。而且,如果該類型是泛型的,那么類型參數(shù)的定義也必須出現(xiàn)在每個(gè)部分的部分定義上。每個(gè)部分定義上類型參數(shù)的名稱和位置必須完全一致。即在每個(gè)部分什么的class、struct或interface關(guān)鍵字之前加partial關(guān)鍵字。而且必須屬于同一個(gè)命名空間。
每個(gè)Windows線程都有一個(gè)私有的內(nèi)存區(qū)塊,稱為棧;也就是說(shuō)這塊內(nèi)存塊不能被其他線程訪問(wèn)(特定條件下除外)。什么條件?
線程的棧主要用于:
- 保存正在執(zhí)行中的方法的傳入實(shí)參值;
- 保存方法返回是需要跳轉(zhuǎn)的本地代碼的地址;
- 保存對(duì)象(但不是全部)。
堆的優(yōu)點(diǎn)是容量比棧大得多。為所有線程所共享。
棧的優(yōu)點(diǎn)是速度比堆快。這主要源于專門(mén)訪問(wèn)棧的IL指令,以及訪問(wèn)棧上的元素?zé)o需同步。
因此,用堆來(lái)存儲(chǔ)大對(duì)象,用棧存儲(chǔ)小對(duì)象。。
C#中的值類型的實(shí)例使用靜態(tài)分配(分配在線程棧上),而引用類型的實(shí)例則使用動(dòng)態(tài)分配(分配在進(jìn)程堆中)。
結(jié)構(gòu)、枚舉是值類型,委托是引用類型
如果某個(gè)類的實(shí)例有個(gè)值類型的字段,那么該字段會(huì)和類實(shí)例保存在一起,即堆中。反過(guò)來(lái),如果一個(gè)結(jié)構(gòu)的字段是引用類型,那么引用類型的實(shí)例還是會(huì)保存在堆中。
在C#中,求模運(yùn)算也可以用于浮點(diǎn)數(shù)。
float a = 5.5f;
Console.WriteLine(a % 2.5);
屏幕上將輸出0.5。
C#語(yǔ)言提供了checked關(guān)鍵字,可以得到驗(yàn)證所有的類型轉(zhuǎn)換和運(yùn)算。如果有問(wèn)題就會(huì)引發(fā)一個(gè)異常。
整形和decimal類型被零除時(shí),會(huì)產(chǎn)生DivideByZeroException異常。
浮點(diǎn)型float和double被零除時(shí),會(huì)得到無(wú)窮大,0/0得到Nan。
C#的遞增和遞減運(yùn)算符也可以用于浮點(diǎn)數(shù)。
float a = 5.5f;
a++;
此時(shí)a = 6.5。
C#中的結(jié)構(gòu)不能從其他類或者結(jié)構(gòu)派生,也不能作為其他類型或結(jié)構(gòu)的基類。
C#的結(jié)構(gòu)可以有多個(gè)構(gòu)造函數(shù),當(dāng)不允許自定義默認(rèn)的構(gòu)造函數(shù)(即沒(méi)有參數(shù)的構(gòu)造函數(shù))。而且編譯器要求每一個(gè)構(gòu)造函數(shù)都初始化結(jié)構(gòu)的所有字段。
默認(rèn)構(gòu)造函數(shù)將所有值類型的字段設(shè)為零,而將所有引用類型的字段設(shè)為空引用。
結(jié)構(gòu)可以有自己的方法。
與類的字段不同,結(jié)構(gòu)的字段不能在聲明中顯示初始化。
結(jié)構(gòu)的實(shí)例常常存儲(chǔ)在棧中,因此結(jié)構(gòu)不宜太大。太大的結(jié)構(gòu)最好用類代替。
編譯器默認(rèn)情況下,將枚舉的值視為int型整數(shù)。因此,枚舉定義的這組常數(shù)中任意一個(gè)值都是一個(gè)整數(shù)。可以對(duì)其進(jìn)行遞增、遞減操作。
在默認(rèn)情況下,枚舉的第一個(gè)值是0,之后的每一個(gè)值都是前一個(gè)值加1.當(dāng)然,也可以手工指定自己想要的值。
你也可以定義其他類型的枚舉類型的值:
??? enum MakerCHB:byte{Beijing,Zhejiang}
??? enum MakerCHL:long{Beijing,Zhejiang}
可以讓一個(gè)枚舉的實(shí)例包含多個(gè)枚舉值。這個(gè)概念也稱為二進(jìn)制位標(biāo)志(binary flag)或者標(biāo)志枚舉(flag enum).
注意,位域枚舉都打上了System.Flags attribute標(biāo)志,該attribute通知CLR和客戶端這個(gè)枚舉用來(lái)表示位域而不是標(biāo)準(zhǔn)枚舉,這個(gè)枚舉用來(lái)表示位域而不是標(biāo)準(zhǔn)枚舉。這個(gè)標(biāo)志會(huì)影響ToString()方法的結(jié)果。最好能有個(gè)實(shí)例!
.NET Framework中的System.Threading.ThreadState就是采用了二進(jìn)制標(biāo)志的枚舉。
C#中String類的實(shí)例是不可變。即無(wú)法修改它們,它們將保持通過(guò)構(gòu)造函數(shù)所賦的值不變。
C#允許定義無(wú)轉(zhuǎn)義的字符串字面常量,方法就是在字符串起始的雙引號(hào)之前加入“@”符號(hào)。無(wú)轉(zhuǎn)義字符串字面常量具有以下特征:
- 它將接受所有字符作為字符串的內(nèi)容,包括“\”反斜杠字符,不過(guò)不包括雙引號(hào)。
- 它將接受字符串中的所有換行。
通過(guò)不安全代碼也可以打破字符串實(shí)例的不可變特性。
C#允許用delegate關(guān)鍵字創(chuàng)建一種特殊的類,我們稱這種類為委托類。委托類的實(shí)例稱為委托對(duì)象。
委托對(duì)象是一種指向一個(gè)或多個(gè)方法(靜態(tài)或非靜態(tài))的引用。我們可以像調(diào)用方法那樣“調(diào)用”委托對(duì)象,這其實(shí)就是調(diào)用委托對(duì)象所引用的方法。注意這些方法的調(diào)用是在調(diào)用委托的方法所在的線程中完成的,即同步調(diào)用。
委托變量所能引用的方法只能是其簽名式與委托類聲明中所提供的簽名式一致的方法。
delegate?void?Deleg1();
delegate?string?Deleg2(string?s);
delegate?void?f1()
{
}
static?string?f2(string?s)
{
}
Deleg1?d1?=?new?Deleg1(f1);???//?right
Deleg2?d2?=?new?Deleg2(f2);???//?right
Deleg2?d3?=?new?Deleg2(f1);???//?error C# 2.0編譯器引入在創(chuàng)建委托變量時(shí)推測(cè)其類型的功能。于是就可以直接將一個(gè)方法賦給隱式創(chuàng)建的對(duì)象。如
Deleg1 d1 = f1;
Deleg2 d2 = f2;
但是,其編譯生成的IL代碼,跟前面的是一樣的,它仍舊調(diào)用了Deleg1和Deleg2委托類的構(gòu)造函數(shù)。
可以用一個(gè)委托對(duì)象應(yīng)用多個(gè)具有相同簽名式的方法(靜態(tài)或非靜態(tài))。這種情況下調(diào)用委托對(duì)象就會(huì)在調(diào)用對(duì)象的線程中順序執(zhí)行所有的方法。調(diào)用方法的順序就是方法添加到委托對(duì)象中的順序,每個(gè)方法的參數(shù)都是一樣的。
如果委托的簽名具有返回值,那么引用多個(gè)方法時(shí)只有最后一個(gè)調(diào)用的方法的返回值才作為委托對(duì)象的返回值返回。
可以用GetInvocationList()獲取該委托對(duì)象中的委托列表。
可空類型System.Nullable<T>等價(jià)于T?。
??? 即int? i = null;和Nullable<int> i = null;是等價(jià)的。
不過(guò),編譯器會(huì)阻止從可空類型到原始類型的隱式轉(zhuǎn)換。此外,不事先測(cè)試而進(jìn)行可空類型到原始類型的顯示轉(zhuǎn)換也是危險(xiǎn)的,因?yàn)?#xff0c;這可能會(huì)引發(fā)InvalidOperationException異常。
C# 2.0允許將類、結(jié)構(gòu)和接口的聲明分散到多個(gè)源文件中。我們稱這一特性命名為部分類型。注意,委托類或者枚舉類是不能聲明在多個(gè)源文件中的。
同一個(gè)類型各個(gè)不同的部分定義前面必須都加partial關(guān)鍵字。而且,如果該類型是泛型的,那么類型參數(shù)的定義也必須出現(xiàn)在每個(gè)部分的部分定義上。每個(gè)部分定義上類型參數(shù)的名稱和位置必須完全一致。即在每個(gè)部分什么的class、struct或interface關(guān)鍵字之前加partial關(guān)鍵字。而且必須屬于同一個(gè)命名空間。
總結(jié)
以上是生活随笔為你收集整理的从C#2.0的角度看.NET 2.0类型系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: show controller e1
- 下一篇: git顶置文章