【正文】
e ) { _coll = new ArrayList( )。 // also 0 Both statements initialize the variable to all 0s. 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 es when you create multiple initializations 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 initialize it. private ArrayList _coll = new ArrayList( )。s not wrongit39。 } Regardless of the number of constructors you eventually addto the MyClass type, _coll will be initialized properly. The piler 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 not need to add initialization code to every constructor。t know 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 finalizer. 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 cycle, those objects that have been finalized are removed from memory. Figure 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 . This sequence shows the effect of finalizers on the Garbage Collector. Objects stay in memory longer, and an extra thread needs to be spawned to run the Garbage Collector. 12 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. It39。t work well. In C, the finalizer eventually executes, but it doesn39。 } }。s job. The GC39。s not plicated enough, you can create DataViews that provide access to filtered sequences of a data table. Those are all managed by a DataViewManager. There are references all through the web of objects that make up a DataSet. Releasing memory is the GC39。s 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 memorymanagement issues. But 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. Here39。做為一個(gè)靜態(tài)的構(gòu)造,你可以這樣 (參見原則 45): static MySingleton( ) { try { _theOneAndOnly = new MySingleton( )。因?yàn)殪o態(tài)構(gòu)造函數(shù)是 CLR調(diào)用的,你必須十分注意異常的產(chǎn)生。 } } private MySingleton( ) { } // remainder elided } 同樣,和實(shí)例的預(yù)置方法一樣,靜態(tài)的預(yù)置方法在靜態(tài)的構(gòu)造函數(shù)調(diào)用前執(zhí)行。 public static MySingleton TheOnly { get { return _theOneAndOnly。你不能用任何的實(shí)例構(gòu)造函數(shù),其它特殊的私有函數(shù), 或者任何其它習(xí)慣方法來初始化一個(gè)變量。 Effective C 原則 13:用靜態(tài)構(gòu)造函數(shù)初始化類的靜態(tài)成員 你應(yīng)該知道,在一個(gè)類型的任何實(shí)例初始化以前,你應(yīng)該初始化它的靜態(tài)成員變量。初始化器在所有的構(gòu)造函數(shù)之前被執(zhí)行。你不能在初始化器中使用 try塊,任何在構(gòu)造時(shí)因成員變量產(chǎn)生的異??赡苎苌綄ο蟮耐饷?。 MyClass( ) { _coll = new ArrayList( )。其中一個(gè)很快成為垃圾對象。你使用初始化器初始化變量,而所有的構(gòu) 造函數(shù)也對這些變量進(jìn)行了初始化。第一個(gè)是通過設(shè)置包含 _MyVal1 的內(nèi)存來置 0。這并沒有錯(cuò),只是效率不高 。系統(tǒng)默認(rèn)會在你任何代碼執(zhí)行前,為所有的內(nèi)容都初始化為 0。初始化會在執(zhí)行類型的基類的構(gòu)造函數(shù)之前被執(zhí)行,并且它們是按你聲明的先后關(guān)系順序執(zhí)行的。當(dāng)你添加了一個(gè)新的變量,你不用在所有的構(gòu)造函數(shù)里添加初始化代碼;直接在聲明的地方對它進(jìn)行初始化就行了。直接賦值: public class MyClass { // declare the collection, and initialize it. private ArrayList _coll = new ArrayList( )。時(shí)間一長,就難得讓 它的成員變量以及構(gòu)造函數(shù)進(jìn)行同步了。析構(gòu)函數(shù)會對你的應(yīng)用程序性能產(chǎn)生一些影響,但你必須使用它們來防止資源泄漏 (譯注:請注意理解非內(nèi)存資源是什么,一般是指文件句柄,網(wǎng)絡(luò)資源,或者其它不能在內(nèi)存中存放的資源 )。如果它還沒有被析構(gòu),它將會移到第 2代對象。 GC通過限制檢測第 1 以及第 2代對象來優(yōu)化它的工作。所有那些經(jīng)過 2次或者 2次以上 GC回收后還存在的對象稱為第 2代對象。 ),使得情況比這復(fù)雜得多。對象會在內(nèi)存里存在的時(shí)間更長,須要啟動另一個(gè)線程來運(yùn)行垃圾回收器。在下一個(gè) GC回收時(shí),那些被析構(gòu)了的對象才會再從內(nèi)存上移除。當(dāng) GC發(fā)現(xiàn)某個(gè)對象是垃圾但是須要析構(gòu)時(shí),它還不能直接從內(nèi)存上刪除這個(gè)對象。它會在后面的某個(gè)未知時(shí)間上運(yùn)行。明確的析構(gòu)函數(shù)不是 .Net環(huán)境或者 C的一 部份。 } }。關(guān)于 GC,本人推薦讀者參考一下 Jeffrey 的.Net框架程序設(shè)計(jì) (修訂版 )中討論的 垃圾回收器 )。析構(gòu)函數(shù)是在垃圾回收器把對象從內(nèi)存移除前,由系統(tǒng)調(diào)用的。 圖 垃圾回收器不僅僅是移動不使用的內(nèi)存,還移除動其它的對象,從而壓縮使用的內(nèi)存,讓出最多的空閑內(nèi)存。而且在每次運(yùn)行時(shí),它還會壓縮托管堆。 GC的設(shè)計(jì)結(jié)構(gòu)可以簡化這些問題,它可以識別這些網(wǎng)頁對象就是垃圾。所有這些貫穿網(wǎng)頁的引用構(gòu)成了 DataSet。而同時(shí), DataTime 也同樣有一個(gè)引用到它的容器上,也就是 DataRow。 GC是通過對從應(yīng)用程序的根對象開始,通過樹形結(jié)構(gòu)的 “漫游 ”來斷定一個(gè)對象是否可達(dá)的,而不是強(qiáng)迫每個(gè)對象都保持一些引用跟蹤, COM 就是這樣的。你要對非托管資源負(fù)責(zé),例