計算機 資源管理 外文翻譯 外文文獻 英文文獻 Effective C# 中文版改善C程序的50種方法第二章.NET

上傳人:仙*** 文檔編號:27991691 上傳時間:2021-08-22 格式:DOC 頁數(shù):19 大小:170.02KB
收藏 版權(quán)申訴 舉報 下載
計算機 資源管理 外文翻譯 外文文獻 英文文獻 Effective C# 中文版改善C程序的50種方法第二章.NET_第1頁
第1頁 / 共19頁
計算機 資源管理 外文翻譯 外文文獻 英文文獻 Effective C# 中文版改善C程序的50種方法第二章.NET_第2頁
第2頁 / 共19頁
計算機 資源管理 外文翻譯 外文文獻 英文文獻 Effective C# 中文版改善C程序的50種方法第二章.NET_第3頁
第3頁 / 共19頁

下載文檔到電腦,查找使用更方便

15 積分

下載資源

還剩頁未讀,繼續(xù)閱讀

資源描述:

《計算機 資源管理 外文翻譯 外文文獻 英文文獻 Effective C# 中文版改善C程序的50種方法第二章.NET》由會員分享,可在線閱讀,更多相關(guān)《計算機 資源管理 外文翻譯 外文文獻 英文文獻 Effective C# 中文版改善C程序的50種方法第二章.NET(19頁珍藏版)》請在裝配圖網(wǎng)上搜索。

1、武漢科技大學本科畢業(yè)論文外文翻譯.NET Resource ManagementBillWagnerEffective C#: 50 Specific Ways to Improve Your C#,Chapter 2,.NET Resource Management,BillWagner,Addison Wesley Professional,2004,77115.NET 資源管理比爾瓦格拉Effective C# 中文版改善C#程序的50種方法,第二章,.NET 資源管理,比爾瓦格拉,2004,77115一個簡單的事實:.Net應(yīng)用程序是在一個托管的環(huán)境里運行的,這個環(huán)境和不同的設(shè)計器有很

2、大的沖突,這就才有了Effective C#。極大限度上的討論這個環(huán)境的好處,須要把你對本地化環(huán)境的想法改變?yōu)?Net CLR。也就意味著要明白.Net的垃圾回收器。在你明白這一章里所推薦的內(nèi)容時,有必要對.Net的內(nèi)存管理環(huán)境有個大概的了解。那我們就開始大概的了解一下吧。垃圾回收器(GC)為你控制托管內(nèi)存。不像本地運行環(huán)境,你不用負責對內(nèi)存泄漏,不定指針,未初始化指針,或者一個其它內(nèi)存管理的服務(wù)問題。但垃圾回收器前不是一個神話:你一樣要自己清理。你要對非托管資源負責,例如文件句柄,數(shù)據(jù)鏈接,GDI+對象,COM對象,以及其它一些系統(tǒng)對象。這有一個好消息:因為GC管理內(nèi)存,明確的設(shè)計風格可以更

3、容易的實現(xiàn)。循環(huán)引用,不管是簡單關(guān)系還是復(fù)雜的網(wǎng)頁對象,都非常容易。GC的標記以及嚴謹?shù)母咝惴梢詸z測到這些關(guān)系,并且完全的刪除不可達的網(wǎng)頁對象。GC是通過對從應(yīng)用程序的根對象開始,通過樹形結(jié)構(gòu)的“漫游”來斷定一個對象是否可達的,而不是強迫每個對象都保持一些引用跟蹤,COM就是這樣的。DataSet就是一個很好的例子,展示了這樣的算法是如何簡化并決定對象的所屬關(guān)系的。DataSet是一個DataTable的集合,而每一個DataTable又是DataRow的集合,每一個DataRow又是DataItem的集合,DataColum定義了這些類型的關(guān)系。這里就有一些從DataItem到它的列的引

4、用。而同時,DataTime也同樣有一個引用到它的容器上,也就是DataRow。DataRow包含引用到DataTable,最后每個對象都包含一個引用到DataSet。如果這還不夠復(fù)雜,那可以創(chuàng)建一個DataView,它提供對經(jīng)過過濾后的數(shù)據(jù)表的順序訪問。這些都是由DataViewManager管理的。所有這些貫穿網(wǎng)頁的引用構(gòu)成了DataSet。釋放內(nèi)存是GC的責任。因為.Net框架的設(shè)計者讓你不必釋放這些對象,這些復(fù)雜的網(wǎng)頁對象引用不會造成問題。沒有必須關(guān)心這些網(wǎng)頁對象的合適的釋放順序,這是GC的工作。GC的設(shè)計結(jié)構(gòu)可以簡化這些問題,它可以識別這些網(wǎng)頁對象就是垃圾。在應(yīng)用程序結(jié)束了對Data

5、Set的引用后,沒有人可以引用到它的子對象了(譯注:就是DataSet里的對象再也引用不到了)。因此,網(wǎng)頁里還有沒有對象循環(huán)引用DataSet,DataTables已經(jīng)一點也不重要了,因為這些對象在應(yīng)用程序都已經(jīng)不能被訪問到了,它們是垃圾了。垃圾回收器在它獨立的線程上運行,用來從你的程序里移除不使用的內(nèi)存。而且在每次運行時,它還會壓縮托管堆。壓縮堆就是把托管堆中活動的對象移到一起,這樣就可以空出連續(xù)的內(nèi)存。圖2.1展示了兩個沒有進行垃圾回收時的內(nèi)存快照。所有的空閑內(nèi)存會在垃圾回收進行后連續(xù)起來。圖2.1 垃圾回收器不僅僅是移動不使用的內(nèi)存,還移除動其它的對象,從而壓縮使用的內(nèi)存,讓出最多的空閑

6、內(nèi)存。 正如你剛開始了解的,垃圾回收器的全部責任就是內(nèi)存管理。但,所有的系統(tǒng)資源都是你自己負責的。你可以通過給自己的類型定義一個析構(gòu)函數(shù),來保證釋放一些系統(tǒng)資源。析構(gòu)函數(shù)是在垃圾回收器把對象從內(nèi)存移除前,由系統(tǒng)調(diào)用的。你可以,也必須這樣來釋放任何你所占用的非托管資源。對象的析構(gòu)函數(shù)有時是在對象成為垃圾之后調(diào)用的,但是在內(nèi)存歸還之前。這個非確定的析構(gòu)函數(shù)意味著在你無法控制對象析構(gòu)與停止使用之間的關(guān)系(譯注:對象的析構(gòu)與對象的無法引用是兩個完全不同的概念。關(guān)于GC,本人推薦讀者參考一下Jeffrey的.Net框架程序設(shè)計(修訂版)中討論的垃圾回收器)。對C+來說這是個重大的改變,并且這在設(shè)計上有一

7、個重大的分歧。有經(jīng)驗的C+程序員寫的類總在構(gòu)造函數(shù)內(nèi)申請內(nèi)存并且在析構(gòu)函數(shù)中釋放它們:/ 好的 C+, 壞的C#:class CriticalSectionpublic: / 構(gòu)造系統(tǒng)需要的資源 CriticalSection( ) EnterCriticalSection( ); / 銷毀資源 CriticalSection( ) ExitCriticalSection( ); ;/ 使用:void Func( ) / 系統(tǒng)資源的生存周期 CriticalSection s; / Do work. /. / compiler generates call to destructor. / c

8、ode exits critical section.這是一種很常見的C+風格,它保證資源無異常的釋放。但這在C#里不工作,至少,與這不同。明確的析構(gòu)函數(shù)不是.Net環(huán)境或者C#的一部份。強行用C+的風格在C#里使用析構(gòu)函數(shù)不會讓它正常的工作。在C#里,析構(gòu)函數(shù)確實是正確的運行了,但它不是即時運行的。在前面那個例子里,代碼最終在critical section上,但在C#里,當析構(gòu)函數(shù)存在時,它并不是在critical section上。它會在后面的某個未知時間上運行。你不知道是什么時候,你也無法知道是什么時候。依懶于析構(gòu)函數(shù)同樣會導(dǎo)致性能上的損失。須要析構(gòu)的對象在垃圾回收器上放置了一劑性能毒

9、藥。當GC發(fā)現(xiàn)某個對象是垃圾但是須要析構(gòu)時,它還不能直接從內(nèi)存上刪除這個對象。首先,它要調(diào)用析構(gòu)函數(shù),但析構(gòu)函數(shù)的調(diào)用不是在垃圾回收器的同一個線程上運行的。取而代之的是,GC不得不把對象放置到析構(gòu)隊列中,讓另一個線程讓執(zhí)行所有的析構(gòu)函數(shù)。GC繼續(xù)它自己的工作,從內(nèi)存上移除其它的垃圾。在下一個GC回收時,那些被析構(gòu)了的對象才會再從內(nèi)存上移除。圖2.2展示了三個內(nèi)存使用不同的GC情況。注意,那些須要析構(gòu)的對象會待在內(nèi)存里,直到下一次GC回收。圖2.2 這個順序展示了析構(gòu)函數(shù)在垃圾回收器上起的作用。對象會在內(nèi)存里存在的時間更長,須要啟動另一個線程來運行垃圾回收器。這用使你相信:那些須要析構(gòu)的對象在內(nèi)

10、存至少多生存一個GC回收循環(huán)。但,我是簡化了這些事。實際上,因為另一個GC的介入(譯注:其實只有一個GC,作者是想引用回收代的問題。),使得情況比這復(fù)雜得多。.Net回收器采用”代“來優(yōu)化這個問題。代可以幫助GC來很快的標識那些看上去看是垃圾的對象。所以從上一次回后開始創(chuàng)建的對象稱為第0代對象,所有那些經(jīng)過一次GC回收后還存在的對象稱為第1代對象。所有那些經(jīng)過2次或者2次以上GC回收后還存在的對象稱為第2代對象。分代的目的就是用來區(qū)分臨時變量以及一些應(yīng)用程序的全局變量。第0代對象很可能是臨時的變量。成員變量,以及一些全局變量很快會成為第1代對象,最終成為第2代對象。GC通過限制檢測第1以及第2

11、代對象來優(yōu)化它的工作。每個GC循環(huán)都檢測第0代對象。粗略假設(shè)個GC會超過10次檢測來檢測第0代對象,而要超過100次來檢測所有對象。再次考慮析構(gòu)函數(shù)的開銷:一個須要析構(gòu)函數(shù)的對象可能要比一個不用析構(gòu)函數(shù)的對象在內(nèi)存里多待上9個GC回收循環(huán)。如果它還沒有被析構(gòu),它將會移到第2代對象。在第2代對象中,一個可以生存上100個GC循環(huán)直到下一個第2代集合。結(jié)束時,記得一個垃圾回收器負責內(nèi)存管理的托管環(huán)境的最大好處:內(nèi)存泄漏,其它指針的服務(wù)問題不在是你的問題。非內(nèi)存資源迫使你要使用析構(gòu)函數(shù)來確保清理非內(nèi)存資源。析構(gòu)函數(shù)會對你的應(yīng)用程序性能產(chǎn)生一些影響,但你必須使用它們來防止資源泄漏(譯注:請注意理解非內(nèi)

12、存資源是什么,一般是指文件句柄,網(wǎng)絡(luò)資源,或者其它不能在內(nèi)存中存放的資源)。通過實現(xiàn)IDisposable接口來避免析構(gòu)函數(shù)在垃圾回收器上造成的性能損失。接下來的具體的原則將會幫助你更有效的使用環(huán)境來開發(fā)程序。Effective C# 原則12:選擇變量初始化而不是賦值語句一些類經(jīng)常不只一個構(gòu)造函數(shù)。時間一長,就難得讓它的成員變量以及構(gòu)造函數(shù)進行同步了。最好的確保這樣的事不會發(fā)生的方法就是:在聲明就是的時間就直接初始化,而不是在每個構(gòu)造函數(shù)內(nèi)進行賦值。而且你應(yīng)該使用初始化器語法同時為靜態(tài)的和實例的變量進行初始化。在C#里,當你聲明一個變量時就自然的構(gòu)造了這個成員變量。直接賦值:public c

13、lass MyClass / declare the collection, and initialize it. private ArrayList _coll = new ArrayList( );忽略你最終會給MyClass添加多少個構(gòu)造函數(shù),_coll會正確的初始化。編譯器會產(chǎn)生一些代碼,使得在你的任何一個構(gòu)造函數(shù)調(diào)用前,都會初始化你聲明的實例變量。當你添加一個新的構(gòu)造函數(shù)時,_coll就給你初始化了。當你添加了一個新的變量,你不用在所有的構(gòu)造函數(shù)里添加初始化代碼;直接在聲明的地方對它進行初始化就行了。同樣重要的是:如果你沒有明確的聲明任何一個構(gòu)造函數(shù),編譯會默認的給你添加一個,并且把

14、所有的變量初始化過程都添加到這個構(gòu)造函數(shù)里。初始化器更像是一個到構(gòu)造函數(shù)的方便的快捷方法。初始化生成的代碼會放置在類型的構(gòu)造函數(shù)之前。初始化會在執(zhí)行類型的基類的構(gòu)造函數(shù)之前被執(zhí)行,并且它們是按你聲明的先后關(guān)系順序執(zhí)行的。使用初始化器是一個最簡單的方法,在你的類型里來避免使用一些沒有賦值的變量,但這并不是很好。下面三種情況下,你不應(yīng)該使用初始化器語法。首先就是,如果你是初始化一個對象為0,或者為null。系統(tǒng)默認會在你任何代碼執(zhí)行前,為所有的內(nèi)容都初始化為0。系統(tǒng)置0的初始化是基于底層的CPU指令,對整個內(nèi)存塊設(shè)置。你的任何其它置0的初始化語句是多余的。C#編譯器忠實的添加額外的指令把內(nèi)存設(shè)置為

15、0。這并沒有錯,只是效率不高。事實上,如果是處理值類型數(shù)據(jù),這是很不值的:MyValType _MyVal1; / initialized to 0MyValType _MyVal2 = new MyValType(); / also 0兩條語句都是把變量置為0。第一個是通過設(shè)置包含_MyVal1的內(nèi)存來置0;而第二個是通過IL指令initobj,這對變量_MyVal2會產(chǎn)生裝箱與拆箱操作。這很要花一點額外的時間(參見原則17)。第二個低效率的是在你為一個對象添加兩個構(gòu)造函數(shù)時會產(chǎn)生。你使用初始化器初始化變量,而所有的構(gòu)造函數(shù)也對這些變量進行了初始化。這個版本的MyClass兩個不同的Arra

16、yList對象在它的構(gòu)造函數(shù)內(nèi):public class MyClass / declare the collection, and initialize it. private ArrayList _coll = new ArrayList( ); MyClass( ) MyClass( int size ) _coll = new ArrayList( size ); 當你創(chuàng)建一個新的MyClass對象時,特別指定集合的大小,你創(chuàng)建了兩個數(shù)組列表。其中一個很快成為垃圾對象。初始化器在所有的構(gòu)造函數(shù)之前會執(zhí)行,構(gòu)造函數(shù)會創(chuàng)建第2個數(shù)組列表。編譯器產(chǎn)生了這個的一個版本,當然這是你決不會手動寫出

17、來的。public class MyClass / declare the collection, and initialize it. private ArrayList _coll; MyClass( ) _coll = new ArrayList( ); MyClass( int size ) _coll = new ArrayList( ); _coll = new ArrayList( size ); 最后一個原因要把初始化放到構(gòu)造函數(shù)里就是促使異常的捕獲。你不能在初始化器中使用try塊,任何在構(gòu)造時因成員變量產(chǎn)生的異??赡苎苌綄ο蟮耐饷妗D銦o法試圖在你的類里來捕獲它。你應(yīng)該把那些

18、初始化代碼移到構(gòu)造函數(shù)里,這樣你就可以捕獲異常從而保證你的代碼很友好(參見原則45)。變量初始化器是一個最簡單的方法,在忽略構(gòu)造函數(shù)時來保證成員變量被正確的初始化。初始化器在所有的構(gòu)造函數(shù)之前被執(zhí)行。使用這樣的語法意味著當你在為后來發(fā)布的版本中添加了構(gòu)造函數(shù)時,不會忘記添加恰當?shù)某跏蓟綐?gòu)造函數(shù)里。當構(gòu)造函數(shù)與初始化生成同樣的成員對象時,就使用初始化器。閱讀簡單而且易于維護。Effective C# 原則13:用靜態(tài)構(gòu)造函數(shù)初始化類的靜態(tài)成員你應(yīng)該知道,在一個類型的任何實例初始化以前,你應(yīng)該初始化它的靜態(tài)成員變量。在里C#你可以使用靜態(tài)的預(yù)置方法和靜態(tài)構(gòu)造函數(shù)來實現(xiàn)這個目的。一個類的靜態(tài)構(gòu)造函

19、數(shù)是一個與眾不同的,它在所有的方法,變量或者屬性訪問前被執(zhí)行。你可以用這個函數(shù)來初始化靜態(tài)成員變量,強制使用單件模式,或者實現(xiàn)其它任何在類型的實例可用前應(yīng)該完成的工作。你不能用任何的實例構(gòu)造函數(shù),其它特殊的私有函數(shù), 或者任何其它習慣方法來初始化一個變量。和實例的預(yù)置方法一樣,你可以把靜態(tài)的預(yù)置方法做為靜態(tài)構(gòu)造函數(shù)可替代的選擇。如果須要簡單的分配一個靜態(tài)成員,就直接使用初始化語法。當你有更復(fù)雜的邏輯來初始化靜態(tài)成員變量時,就創(chuàng)建一個靜態(tài)構(gòu)造函數(shù):public class MySingleton private static readonly MySingleton _theOneAndOnly

20、 = new MySingleton( ); public static MySingleton TheOnly get return _theOneAndOnly; private MySingleton( ) / remainder elided可以用下面的方法簡單的實現(xiàn)單件模式,實際上你在初始化一個單件模式時可能有更復(fù)雜的邏輯:public class MySingleton private static readonly MySingleton _theOneAndOnly; static MySingleton( ) _theOneAndOnly = new MySingleton(

21、 ); public static MySingleton TheOnly get return _theOneAndOnly; private MySingleton( ) / remainder elided同樣,和實例的預(yù)置方法一樣,靜態(tài)的預(yù)置方法在靜態(tài)的構(gòu)造函數(shù)調(diào)用前執(zhí)行。并且,你的靜態(tài)預(yù)置方法在基類的靜態(tài)構(gòu)造函數(shù)執(zhí)行前被執(zhí)行。當應(yīng)用程序第一次裝載你的數(shù)據(jù)類型時,CLR自動調(diào)用靜態(tài)構(gòu)造函數(shù)。你只能定義一個靜態(tài)構(gòu)造函數(shù),并且不能有參數(shù)。因為靜態(tài)構(gòu)造函數(shù)是CLR調(diào)用的,你必須十分注意異常的產(chǎn)生。如果在靜態(tài)構(gòu)造函數(shù)里產(chǎn)生了異常,CLR將會直接終止你的應(yīng)用程序。正因為異常,靜態(tài)構(gòu)造函數(shù)常常代替

22、靜態(tài)預(yù)置方法。如果你使用靜態(tài)預(yù)置方法,你自己不能捕獲異常。做為一個靜態(tài)的構(gòu)造,你可以這樣(參見原則45):static MySingleton( ) try _theOneAndOnly = new MySingleton( ); catch / Attempt recovery here. 靜態(tài)預(yù)置方法和靜態(tài)構(gòu)造函數(shù)為你的類提供了最清爽的方法來初始化靜態(tài)成員。與其它語言不同,它們被添加到C#語言中,是初始化靜態(tài)成員的兩個不同的特殊位置。The simple fact that .NET programs run in a managed environment has a big impac

23、t on the kinds of designs that create effective C#. Taking utmost advantage of that environment requires changing your thinking from native environments to the .NET CLR. It means understanding the .NET Garbage Collector. An overview of the .NET memory management environment is necessary to understan

24、d the specific recommendations in this chapter, so lets get on with the overview.The Garbage Collector (GC) controls managed memory for you. Unlike native environments, you are not responsible for memory leaks, dangling pointers, uninitialized pointers, or a host of other memory-management issues. B

25、ut the Garbage Collector is not magic: You need to clean up after yourself, too. You are responsible for unmanaged resources such as file handles, database connections, GDI+ objects, COM objects, and other system objects.Heres the good news: Because the GC controls memory, certain design idioms are

26、much easier to implement. Circular references, both simple relationships and complex webs of objects, are much easier. The GCs Mark and Compact algorithm efficiently detects these relationships and removes unreachable webs of objects in their entirety. The GC determines whether an object is reachabl

27、e by walking the object tree from the applications root object instead of forcing each object to keep track of references to it, as in COM. The DataSet class provides an example of how this algorithm simplifies object ownership decisions. A DataSet is a collection of DataTables. Each DataTable is a

28、collection of DataRows. Each DataRow is a collection of DataItems. Each DataTable also contains a collection of DataColumns. DataColumns define the types associated with each column of data. There are other references from the DataItems to its appropriate column. Every DataItem also contains a refer

29、ence to its container, the DataRow. DataRows contain references back to the DataTable, and everything contains a reference back to the containing DataSet.If thats not complicated enough, you can create DataViews that provide access to filtered sequences of a data table. Those are all managed by a Da

30、taViewManager. There are references all through the web of objects that make up a DataSet. Releasing memory is the GCs responsibility. Because the .NET Framework designers did not need to free these objects, the complicated web of object references did not pose a problem. No decision needed to be ma

31、de regarding the proper sequence of freeing this web of objects; its the GCs job. The GCs design simplifies the problem of identifying this kind of web of objects as garbage. After the application releases its reference to the dataset, none of the subordinate objects can be reached. It does not matt

32、er that there are still circular references to the DataSet, DataTables, and other objects in the web. Because these objects cannot be reached from the application, they are all garbage.The Garbage Collector runs in its own thread to remove unused memory from your program. It also compacts the manage

33、d heap each time it runs. Compacting the heap moves each live object in the managed heap so that the free space is located in one contiguous block of memory. Figure 2.1 shows two snapshots of the heap before and after a garbage collection. All free memory is placed in one contiguous block after each

34、 GC operation.Figure 2.1. The Garbage Collector not only removes unused memory, but it moves other objects in memory to compact used memory and maximize free space.As youve just learned, memory management is completely the responsibility of the Garbage Collector. All other system resources are your

35、responsibility. You can guarantee that you free other system resources by defining a finalizer in your type. Finalizers are called by the system before an object that is garbage is removed from memory. You canand mustuse these methods to release any unmanaged resources that an object owns. The final

36、izer for an object is called at some time after it becomes garbage and before the system reclaims its memory. This nondeterministic finalization means that you cannot control the relationship between when you stop using an object and when its finalizer executes. That is a big change from C+, and it

37、has important ramifications for your designs. Experienced C+ programmers wrote classes that allocated a critical resource in its constructor and released it in its destructor:/ Good C+, bad C#:class CriticalSectionpublic: / Constructor acquires the system resource. CriticalSection( ) EnterCriticalSe

38、ction( ); / Destructor releases system resource. CriticalSection( ) ExitCriticalSection( ); ;/ usage:void Func( ) / The lifetime of s controls access to / the system resource. CriticalSection s; / Do work. /. / compiler generates call to destructor. / code exits critical section.This common C+ idiom

39、 ensures that resource deallocation is exception-proof. This doesnt work in C#, howeverat least, not in the same way. Deterministic finalization is not part of the .NET environment or the C# language. Trying to force the C+ idiom of deterministic finalization into the C# language wont work well. In

40、C#, the finalizer eventually executes, but it doesnt execute in a timely fashion. In the previous example, the code eventually exits the critical section, but, in C#, it doesnt exit the critical section when the function exits. That happens at some unknown time later. You dont know when. You cant kn

41、ow when.Relying on finalizers also introducesperformance penalties. Objects that require finalization put a performance drag on the Garbage Collector. When the GC finds that an object is garbage but also requires finalization, it cannot remove that item from memory just yet. First, it calls the fina

42、lizer. Finalizers are not executed by the same thread that collects garbage. Instead, the GC places each object that is ready for finalization in a queue and spawns yet another thread to execute all the finalizers. It continues with its business, removing other garbage from memory. On the next GC cy

43、cle, those objects that have been finalized are removed from memory. Figure 2.2 shows three different GC operations and the difference in memory usage. Notice that the objects that require finalizers stay in memory for extra cycles.Figure 2.2. This sequence shows the effect of finalizers on the Garb

44、age Collector. Objects stay in memory longer, and an extra thread needs to be spawned to run the Garbage Collector. This might lead you to believe that an object that requires finalization lives in memory for one GC cycle more than necessary. But I simplified things. Its more complicated than that b

45、ecause of another GC design decision. The .NET Garbage Collector defines generations to optimize its work. Generations help the GC identify the likeliest garbage candidates more quickly. Any object created since the last garbage collection operation is a generation 0 object. Any object that has surv

46、ived one GC operation is a generation 1 object. Any object that has survived two or more GC operations is a generation 2 object. The purpose of generations is to separate local variables and objects that stay around for the life of the application. Generation 0 objects are mostly local variables. Me

47、mber variables and global variables quickly enter generation 1 and eventually enter generation 2.The GC optimizes its work by limiting how often it examines first- and second-generation objects. Every GC cycle examines generation 0 objects. Roughly 1 GC out of 10 examines the generation 0 and 1 obje

48、cts. Roughly 1 GC cycle out of 100 examines all objects. Think about finalization and its cost again: An object that requires finalization might stay in memory for nine GC cycles more than it would if it did not require finalization. If it still has not been finalized, it moves to generation 2. In g

49、eneration 2, an object lives for an extra 100 GC cycles until the next generation 2 collection.To close, remember that a managed environment, where the Garbage Collector takes the responsibility for memory management, is a big plus: Memory leaks and a host of other pointer-related problems are no lo

50、nger your problem. Nonmemory resources force you to create finalizers to ensure proper cleanup of those nonmemory resources. Finalizers can have a serious impact on the performance of your program, but you must write them to avoid resource leaks. Implementing and using the IDisposable interface avoi

51、ds the performance drain on the Garbage Collector that finalizers introduce. The next section moves on to the specific items that will help you create programs that use this environment more effectively.Item 12: Prefer Variable Initializers to Assignment StatementsClasses often have more than one co

52、nstructor. Over time, its easy for the member variables and the constructors to get out of synch. The best way to make sure this doesnt happen is to initialize variables where you declare them instead of in the body of every constructor. You should utilize the initializer syntax for both static and

53、instance variables.Constructing member variables when you declare that variable is natural in C#. Just assign a value:public class MyClass / declare the collection, and initialize it. private ArrayList _coll = new ArrayList( );Regardless of the number of constructors you eventually addto the MyClass

54、 type, _coll will be initialized properly. The compiler generates code at the beginning of each constructor to execute all the initializers you have defined for your instance member variables. When you add a new constructor, _coll gets initialized. Similarly, if you add a new member variable, you do

55、 not need to add initialization code to every constructor; initializing the variable where you define it is sufficient. Equally important, the initializers are added to the compiler-generated default constructor. The C# compiler creates a default constructor for your types whenever you dont explicit

56、ly define any constructors.Initializers are more than a convenient shortcut for statements in a constructor body. The statements generated by initializers are placed in object code before the body of your constructors. Initializers execute before the base class constructor for your type executes, an

57、d they are executed in the order the variables are declared in your class.Using initializers is the simplest way to avoid uninitialized variables in your types, but its not perfect. In three cases, you should not use the initializer syntax. The first is when you are initializing the object to 0, or

58、null. The default system initialization sets everything to 0 for you before any of your code executes. The system-generated 0 initialization is done at a very low level using the CPU instructions to set the entire block of memory to 0. Any extra 0 initialization on your part is superfluous. The C# c

59、ompiler dutifully adds the extra instructions to set memory to 0 again. Its not wrongits just inefficient. In fact, when value types are involved, its very inefficient.MyValType _MyVal1; / initialized to 0MyValType _MyVal2 = new MyValType(); / also 0Both statements initialize the variable to all 0s.

60、 The first does so by setting the memory containing MyVal1 to 0. The second uses the IL instruction initobj, which causes both a box and an unbox operation on the _MyVal2 variable. This takes quite a bit of extra time (see Item 17).The second inefficiency comes when you create multiple initializatio

61、ns for the same object. You should use the initializer syntax only for variables that receive the same initialization in all constructors. This version of MyClass has a path that creates two different ArrayList objects as part of its construction:public class MyClass / declare the collection, and in

62、itialize it. private ArrayList _coll = new ArrayList( ); MyClass( ) MyClass( int size ) _coll = new ArrayList( size ); When you create a new MyClass, specifying the size of the collection, you create two array lists. One is immediately garbage. The variable initializer executes before every construc

63、tor. The constructor body creates the second array list. The compiler creates this version of MyClass, which you would never code by hand. (For the proper way to handle this situation, see Item 14.)public class MyClass / declare the collection, and initialize it. private ArrayList _coll; MyClass( ) _coll = new ArrayList( ); MyClass( int size ) _coll = new ArrayList( ); _coll = new ArrayList( size ); The final reason to move initialization into the body of a constructor is to facilitate exception handling. You cannot wrap the in

展開閱讀全文
溫馨提示:
1: 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
2: 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
3.本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
5. 裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

相關(guān)資源

更多
正為您匹配相似的精品文檔
關(guān)于我們 - 網(wǎng)站聲明 - 網(wǎng)站地圖 - 資源地圖 - 友情鏈接 - 網(wǎng)站客服 - 聯(lián)系我們

copyright@ 2023-2025  zhuangpeitu.com 裝配圖網(wǎng)版權(quán)所有   聯(lián)系電話:18123376007

備案號:ICP2024067431-1 川公網(wǎng)安備51140202000466號


本站為文檔C2C交易模式,即用戶上傳的文檔直接被用戶下載,本站只是中間服務(wù)平臺,本站所有文檔下載所得的收益歸上傳人(含作者)所有。裝配圖網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對上載內(nèi)容本身不做任何修改或編輯。若文檔所含內(nèi)容侵犯了您的版權(quán)或隱私,請立即通知裝配圖網(wǎng),我們立即給予刪除!