小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

.NET 編程基礎(chǔ)知識(shí)

 weijianian 2016-08-07


來(lái)源:B.it

鏈接:http://www.cnblogs.com/ImBit/p/5484920.html


一、const和readonly


當(dāng)編譯期常量const被編譯成IL時(shí),它就已經(jīng)被替換成所代表的字面數(shù)值。所以更改一個(gè)公有的編譯期常量的值,需要重新編譯所有引用到該常量的代碼以保證所有代碼使用的是最新的常量值。


相反,運(yùn)行時(shí)常量被編譯成IL時(shí)引用的是readonly的變量,而不是變量的值,只需要重新編譯更改了常量值的代碼,就能實(shí)現(xiàn)對(duì)其它已經(jīng)發(fā)布的代碼在二進(jìn)制層次上的兼容。


二、is、as


分兩種情況:


轉(zhuǎn)換的目標(biāo)類(lèi)型是引用類(lèi)型:使用is測(cè)試能否轉(zhuǎn)換成功,然后再用as進(jìn)行轉(zhuǎn)換(as在轉(zhuǎn)換對(duì)象為null時(shí)會(huì)返回null)。as和is不會(huì)執(zhí)行用戶(hù)自定義的轉(zhuǎn)換,只有當(dāng)運(yùn)行時(shí)類(lèi)型是目標(biāo)類(lèi)型或者是目標(biāo)的派生類(lèi)型,才會(huì)轉(zhuǎn)換成功。執(zhí)行用戶(hù)自定義的轉(zhuǎn)換可以用強(qiáng)制轉(zhuǎn)換。


轉(zhuǎn)換的目標(biāo)類(lèi)型是值類(lèi)型:不能使用as,可以使用強(qiáng)制轉(zhuǎn)換。


三、條件編譯#if #endif和Conditional特性


兩者都適用于日常調(diào)試。


#if 可以穿插在函數(shù)中添加條件性代碼,但使用Conditional特性可以限制在函數(shù)層面上將條件性的代碼(如DEBUG)分離出來(lái),保證代碼的良好結(jié)構(gòu)。


四、等同性判斷


(1)等同性在數(shù)學(xué)方面的幾個(gè)要點(diǎn):


自反(reflexive):表示任何對(duì)象都和其自身相等,無(wú)論a是什么類(lèi)型,a==a都應(yīng)該返回true;


對(duì)稱(chēng)(symmetric):意味著等同性判斷時(shí)的順序是無(wú)關(guān)緊要的,若a==b返回true,那么b==a也必然返回true;


可傳遞(transitive):含義是若a==b且b==c都返回true,那么a==c也必然返回true;


值相等(對(duì)應(yīng)于值類(lèi)型):如果兩個(gè)值類(lèi)型的變量類(lèi)型相同,且包含同樣的內(nèi)容,則“值相等”;


引用相等(對(duì)應(yīng)于引用類(lèi)型):如果兩個(gè)引用類(lèi)型的變量指向的是同一個(gè)對(duì)象,則“引用相等”;


(2)C#中等同性判斷的四個(gè)方法


public static bool ReferenceEquals(object left,object right)


無(wú)論比較的是值類(lèi)型還是引用類(lèi)型,該方法判斷的依據(jù)都是對(duì)象標(biāo)識(shí)。所以用來(lái)比較兩個(gè)值類(lèi)型,結(jié)果永遠(yuǎn)都是false,其原因在于裝箱。在創(chuàng)建自己的類(lèi)時(shí),幾乎不需要覆寫(xiě)。


public static bool Equals(object left,object right)


當(dāng)不知道兩個(gè)變量的運(yùn)行時(shí)類(lèi)型時(shí),使用該方法進(jìn)行判斷。其內(nèi)部實(shí)現(xiàn)先引用ReferenceEquals進(jìn)行判斷,再拿left和right與null判斷,最后使用left.Equals(right)判斷。在創(chuàng)建自己的類(lèi)時(shí),幾乎不需要覆寫(xiě)。


public virtual bool Equals(objcet rigth)


有兩種情況:


對(duì)于引用類(lèi)型System.Object:使用對(duì)象標(biāo)識(shí)作為判斷,即比較兩個(gè)對(duì)象是否“引用相等”,默認(rèn)實(shí)現(xiàn)與ReferenceEquals完全一致。新建引用類(lèi)型時(shí)無(wú)需覆寫(xiě)。\


對(duì)于值類(lèi)型System.ValueType:覆寫(xiě)了System.Object中的該方法,實(shí)現(xiàn)了判斷是否”值相等“。因?yàn)闊o(wú)法得知當(dāng)前具體的值類(lèi)型,所以使用了反射,效率較低。建議在新建值類(lèi)型時(shí)覆寫(xiě)該方法,覆寫(xiě)的同時(shí)也要覆寫(xiě)GetHashCode()方法。


public static bool operator==(MyClass left,MyClass right)


引用類(lèi)型System.Object:使用對(duì)象標(biāo)識(shí)作為判斷。


值類(lèi)型System.ValueType:覆寫(xiě)了System.Object中的該方法,因?yàn)闊o(wú)法得知當(dāng)前具體的值類(lèi)型,所以使用了反射,效率較低。建議在新建值類(lèi)型時(shí)覆寫(xiě)該方法,覆寫(xiě)的同時(shí)也要覆寫(xiě)GetHashCode()方法。


五、GetHashCode()陷阱


在引用類(lèi)型(System.Object)中:GetHashCode()能正常工作,雖然它不必然會(huì)產(chǎn)生一個(gè)高效的分布。


在值類(lèi)型(System.ValueType)中:只有在struct的第一個(gè)字段是只讀的情況下,GetHashCode()才能正常工作,只有當(dāng)?shù)谝粋€(gè)字段包含的值有著相對(duì)隨機(jī)的分布,GetHashCode()才會(huì)產(chǎn)生一個(gè)比較高效的散列碼。



GetHashCode覆寫(xiě)規(guī)則


  1. 如果兩個(gè)對(duì)象相等(由operator==判斷),那么它們必須生成相同散列碼。否則,這樣的散列碼將無(wú)法用來(lái)查找容器中的對(duì)象。System.Object:滿(mǎn)足此規(guī)則;System.ValueType:并非所有參與等同性判斷的屬性都會(huì)用來(lái)進(jìn)行散列碼計(jì)算,而是返回struct類(lèi)型中定義的第一個(gè)字段的散列碼作為當(dāng)前值類(lèi)型的散列碼,所以可以認(rèn)定等同性判斷相等的散列碼肯定相等(反過(guò)來(lái),散列碼相等同性判斷不一定相等)。滿(mǎn)足此規(guī)則。


2.對(duì)于任何一個(gè)對(duì)象A,A.GetHashCode()必須保持不變。不管在A上調(diào)用什么方法,A.GetHashCode()都必然總是返回同一個(gè)值。這樣可以確保放在“桶”中的對(duì)象總是位于正確的“桶”中。System.Object:滿(mǎn)足此規(guī)則;System.ValueType:struct中的第一個(gè)字段是一個(gè)常量字段,不會(huì)在生存期發(fā)生改變(稱(chēng)為不可變的值類(lèi)型),滿(mǎn)足此規(guī)則。


3.對(duì)于所有的輸入,散列函數(shù)應(yīng)該在所有整數(shù)中按照隨機(jī)分布生成散列碼。這樣,散列容器才能得到足夠的效率提升。System.Object:系統(tǒng)每創(chuàng)建一個(gè)對(duì)象時(shí)會(huì)指派一個(gè)唯一的對(duì)象鍵(一個(gè)整數(shù)值),從1開(kāi)始,每創(chuàng)建一個(gè)任意類(lèi)型的新對(duì)象,鍵值會(huì)隨之增長(zhǎng),雖然System.Object.GetHashCode()能正常工作,但因?yàn)椴皇请S機(jī)分布,效率不高,所以沒(méi)有滿(mǎn)足此規(guī)則,新建引用類(lèi)型時(shí)建議覆寫(xiě)GetHashCode();System.ValueType:依賴(lài)于第一個(gè)字段的使用方式,如果取任意值,GetHashCode()可以產(chǎn)生比較均勻的分布,但如果取相同的值則沒(méi)有此滿(mǎn)足規(guī)則。


六、委托


內(nèi)建的委托形式


  • Predicate:表示一個(gè)提供布爾型返回值的函數(shù);


  •  Action:接受任意參數(shù)目的參數(shù);


  •  Func:接受零到多個(gè)參數(shù),并返回單一結(jié)果;


.NET的委托都是多播委托(multicast delegate),多播委托將會(huì)把所有添加到該委托中的所有目標(biāo)函數(shù)組合成一個(gè)單一的調(diào)用。有兩點(diǎn)需要注意:


  1. 在多播委托調(diào)用過(guò)程中,每個(gè)目標(biāo)函數(shù)會(huì)被依次調(diào)用。委托對(duì)象本身不會(huì)捕獲異常。因此,任何目標(biāo)拋出的異常都會(huì)結(jié)束委托鏈的調(diào)用,如果有委托調(diào)用出現(xiàn)異常,那么這種方式不能保證安全;


  2. 整個(gè)調(diào)用的返回值將為最后一個(gè)函數(shù)調(diào)用的返回值,前面函數(shù)的返回值將會(huì)被忽略;


解決方法:自己遍歷調(diào)用列表,調(diào)用委托鏈上的每個(gè)目標(biāo)函數(shù)



委托應(yīng)用于回調(diào)


接受Predicate<>、Action<>、Func<>為參數(shù)的方法,如List.Find(Predicate p);有時(shí)傳入lambda表達(dá)式,編譯器會(huì)把lambda表達(dá)式轉(zhuǎn)換成方法,然后創(chuàng)建一個(gè)委托,指向該方法,然后調(diào)用委托實(shí)現(xiàn)回調(diào)。


委托應(yīng)用于事件


.NET的事件模式就是觀察者模式
public event EventHandler Log;


編譯器會(huì)自動(dòng)創(chuàng)建類(lèi)似下面的代碼,根據(jù)需要可以自己編寫(xiě)


private EventHander log;
public event  EventHander Log
{
add{log=log+value;}
remove{log=log-value;}
}


事件相當(dāng)于一個(gè)委托集合,可以添加多個(gè)同類(lèi)型委托(通過(guò)+=);


委托可以添加多個(gè)同類(lèi)型方法(通過(guò)構(gòu)造函數(shù)或+=);


七、資源管理


托管堆上的內(nèi)存由GC(Garbage Collector 垃圾收集器,CLR中包含GC)進(jìn)行管理,其它資源由開(kāi)發(fā)者負(fù)責(zé)。


.NET 提供兩種管理非托管資源生命周期的機(jī)制:終結(jié)器(finalizer,由GC調(diào)用,調(diào)用發(fā)生在對(duì)象成為垃圾之后的某個(gè)時(shí)間,時(shí)間不可預(yù)料)和IDisposable接口。


(1)GC


GC能夠判斷某個(gè)實(shí)體目前是否依舊被應(yīng)用程序的活動(dòng)對(duì)象所引用,對(duì)于那些沒(méi)有被活動(dòng)對(duì)象直接或間接引用的實(shí)體,GC會(huì)將其判斷為垃圾。


GC會(huì)在每次運(yùn)行時(shí)壓縮托管堆,壓縮托管堆能夠?qū)?dāng)前仍舊使用的對(duì)象放在連續(xù)的內(nèi)存中,因此空余空間也是一塊連續(xù)的內(nèi)存。



(2)終結(jié)器


終結(jié)器只是一種防御手段,僅僅能夠保證給定類(lèi)型的對(duì)象所分配的非托管資源最終被釋放。GC會(huì)把需要執(zhí)行終結(jié)的對(duì)象放在專(zhuān)門(mén)的隊(duì)列中,然后讓另一個(gè)線(xiàn)程來(lái)執(zhí)行這些對(duì)象的終結(jié)器。這樣,GC可以繼續(xù)執(zhí)行其當(dāng)前的工作,在內(nèi)存中移除垃圾對(duì)象,而在下一次的GC調(diào)用中才會(huì)從內(nèi)存中移除這些已被終結(jié)的對(duì)象。


可以看到,需要調(diào)用終結(jié)器的對(duì)象將在內(nèi)存中多停留一個(gè)GC周期的時(shí)間(實(shí)際情況會(huì)比這個(gè)更復(fù)雜一點(diǎn),詳情請(qǐng)查看下面“代”的概念),所以應(yīng)該盡量少讓代碼的邏輯使用到終結(jié)器。



GC為了優(yōu)化執(zhí)行,引入了“代”(generation)的概念??梢钥焖俚卣业侥切└锌赡苁抢膶?duì)象。自上一次垃圾收集以來(lái),新創(chuàng)建的對(duì)象屬于第0代對(duì)象。若某個(gè)對(duì)象在經(jīng)歷過(guò)一次垃圾收集之后仍舊存活,那么將成為第1代對(duì)象。兩次及兩次以上垃圾收集后仍沒(méi)有被銷(xiāo)毀的對(duì)象就變成了第2代對(duì)象。


這樣能將局部變量和應(yīng)用程序生命周期一直使用的對(duì)象分開(kāi)對(duì)待。第0代大多屬于局部變量。而成員變量和全局變量則會(huì)更快地成為第1代對(duì)象,直至第2代。GC將通過(guò)減少檢查第1代和第2代對(duì)象的次數(shù)來(lái)優(yōu)化執(zhí)行過(guò)程。在每個(gè)周期中,GC都會(huì)檢查第0代對(duì)象。一般來(lái)說(shuō),大概10個(gè)周期的GC中,會(huì)有一次去同時(shí)檢查第0代和第1代對(duì)象。


大概100個(gè)周期的GC中,會(huì)有一次同時(shí)檢查所有對(duì)象??梢钥吹揭粋€(gè)需要總結(jié)的對(duì)象可能會(huì)比普通對(duì)象多停留9個(gè)GC周期。而若是再次GC的時(shí)候仍沒(méi)有完成終結(jié)炒作,那么該對(duì)象將繼續(xù)被提升為第2代。對(duì)于第2代的對(duì)象,往往需要100次以上的GC周期才會(huì)有機(jī)會(huì)被清除。為了避免這個(gè)性能問(wèn)題,建議使用IDisposable接口。


(3)Dispose()和Close()


使用了非系統(tǒng)資源的類(lèi)型會(huì)自動(dòng)在終結(jié)器中調(diào)用Dispose(),以便在使用者忘記的時(shí)候仍保證能正常釋放資源,但這些資源會(huì)在內(nèi)存中停留更長(zhǎng)時(shí)間,所以最好的方案還是由使用者自己顯示地使用IDisposable接口的Dispose()來(lái)釋放。Dispose()并不是將對(duì)象從內(nèi)存中移除,而只是讓對(duì)象釋放掉其中的非托管資源。


Dispose()和Close()的區(qū)別(Dispose()比Close()要好一些)


Close:清理資源,對(duì)象已經(jīng)不需要被終結(jié),但一般沒(méi)有調(diào)用GC.SuppressFinalize(),所以對(duì)象仍舊在終結(jié)隊(duì)列中。


Dispose:清理資源,調(diào)用GC.SuppressFinalize()告知GC該對(duì)象不再需要被終結(jié)


使用IDisposable.Dispose()實(shí)現(xiàn)銷(xiāo)毀非托管資源的標(biāo)準(zhǔn)銷(xiāo)毀模式


  1. 釋放所有非托管資源;


  2. 釋放所有托管資源,包括釋放事件監(jiān)聽(tīng)程序;


  3. 設(shè)定一個(gè)狀態(tài)標(biāo)識(shí),表示該對(duì)象已經(jīng)被銷(xiāo)毀。若是在銷(xiāo)毀后再次對(duì)用對(duì)象的公有方法,那么應(yīng)該拋出ObjectDisposed異常;


  4. 調(diào)用GC.SuppressFinalize(this),跳過(guò)終結(jié)操作;


(4)using


using語(yǔ)句能以最簡(jiǎn)單的方式保證用戶(hù)的對(duì)象可以正常銷(xiāo)毀,即使對(duì)象在調(diào)用操作時(shí)出現(xiàn)異常。當(dāng)有多個(gè)對(duì)象需要銷(xiāo)毀時(shí),可以使用多個(gè)using塊或一個(gè)try/finally塊。


using(){}=try{}finally{xxx.Dispose();}


下面例子能保證當(dāng)obj不為null時(shí)正確清理到對(duì)象,當(dāng)obj為null時(shí),using(null)也不會(huì)報(bào)錯(cuò),但不會(huì)做任何清理工作。


object obj=Factory.CreateInstance();
using(obj as IDisposable)
{
Console.Write(obj.ToString());
}


八、創(chuàng)建第一個(gè)實(shí)例所進(jìn)行的操作順序


創(chuàng)建某個(gè)類(lèi)型的第一個(gè)實(shí)例時(shí)所進(jìn)行的操作順序,創(chuàng)建同樣類(lèi)型的第二個(gè)以及以后的實(shí)例將從第5步開(kāi)始執(zhí)行


  1. 靜態(tài)變量設(shè)置為0;


  2. 執(zhí)行靜態(tài)變量初始化器;


  3. 執(zhí)行基類(lèi)的靜態(tài)構(gòu)造函數(shù);


  4. 執(zhí)行靜態(tài)構(gòu)造函數(shù);


  5. 實(shí)例變量設(shè)置為0;


  6. 執(zhí)行實(shí)例變量初始化器;


  7. 執(zhí)行基類(lèi)中合適的實(shí)例構(gòu)造函數(shù);


  8. 執(zhí)行實(shí)例構(gòu)造函數(shù);


九、編譯的生命周期



    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多