【正文】
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。做為一個靜態(tài)的構造,你可以這樣 (參見原則 45): static MySingleton( ) { try { _theOneAndOnly = new MySingleton( )。因為靜態(tài)構造函數是 CLR調用的,你必須十分注意異常的產生。 } } private MySingleton( ) { } // remainder elided } 同樣,和實例的預置方法一樣,靜態(tài)的預置方法在靜態(tài)的構造函數調用前執(zhí)行。 public static MySingleton TheOnly { get { return _theOneAndOnly。你不能用任何的實例構造函數,其它特殊的私有函數, 或者任何其它習慣方法來初始化一個變量。 Effective C 原則 13:用靜態(tài)構造函數初始化類的靜態(tài)成員 你應該知道,在一個類型的任何實例初始化以前,你應該初始化它的靜態(tài)成員變量。初始化器在所有的構造函數之前被執(zhí)行。你不能在初始化器中使用 try塊,任何在構造時因成員變量產生的異??赡苎苌綄ο蟮耐饷?。 MyClass( ) { _coll = new ArrayList( )。其中一個很快成為垃圾對象。你使用初始化器初始化變量,而所有的構 造函數也對這些變量進行了初始化。第一個是通過設置包含 _MyVal1 的內存來置 0。這并沒有錯,只是效率不高 。系統(tǒng)默認會在你任何代碼執(zhí)行前,為所有的內容都初始化為 0。初始化會在執(zhí)行類型的基類的構造函數之前被執(zhí)行,并且它們是按你聲明的先后關系順序執(zhí)行的。當你添加了一個新的變量,你不用在所有的構造函數里添加初始化代碼;直接在聲明的地方對它進行初始化就行了。直接賦值: public class MyClass { // declare the collection, and initialize it. private ArrayList _coll = new ArrayList( )。時間一長,就難得讓 它的成員變量以及構造函數進行同步了。析構函數會對你的應用程序性能產生一些影響,但你必須使用它們來防止資源泄漏 (譯注:請注意理解非內存資源是什么,一般是指文件句柄,網絡資源,或者其它不能在內存中存放的資源 )。如果它還沒有被析構,它將會移到第 2代對象。 GC通過限制檢測第 1 以及第 2代對象來優(yōu)化它的工作。所有那些經過 2次或者 2次以上 GC回收后還存在的對象稱為第 2代對象。 ),使得情況比這復雜得多。對象會在內存里存在的時間更長,須要啟動另一個線程來運行垃圾回收器。在下一個 GC回收時,那些被析構了的對象才會再從內存上移除。當 GC發(fā)現某個對象是垃圾但是須要析構時,它還不能直接從內存上刪除這個對象。它會在后面的某個未知時間上運行。明確的析構函數不是 .Net環(huán)境或者 C的一 部份。 } }。關于 GC,本人推薦讀者參考一下 Jeffrey 的.Net框架程序設計 (修訂版 )中討論的 垃圾回收器 )。析構函數是在垃圾回收器把對象從內存移除前,由系統(tǒng)調用的。 圖 垃圾回收器不僅僅是移動不使用的內存,還移除動其它的對象,從而壓縮使用的內存,讓出最多的空閑內存。而且在每次運行時,它還會壓縮托管堆。 GC的設計結構可以簡化這些問題,它可以識別這些網頁對象就是垃圾。所有這些貫穿網頁的引用構成了 DataSet。而同時, DataTime 也同樣有一個引用到它的容器上,也就是 DataRow。 GC是通過對從應用程序的根對象開始,通過樹形結構的 “漫游 ”來斷定一個對象是否可達的,而不是強迫每個對象都保持一些引用跟蹤, COM 就是這樣的。你要對非托管資源負責,例