做法 11
認識 .NET 資源管理
1. 簡易圖示記憶體區塊的關聯圖
2. 記憶體排列物件的放置位址
呼叫 GC 後,記憶體位置改變了,這就是記憶體回收的概念
3. 記憶體層代
層代 0
最新的層代而且包含存留較短的物件。大部分物件都會在層代 0 的記憶體回收,而且不會存留至下一個層代。記憶體回收從第 0 個層代開始。
層代 1
這個層代包含存留較短的物件,且當做較短與較長物件的緩衝區。層代 0 回收後,將壓縮可取得的物件,升階至層代 1。
層代 0 已滿時,記憶體會執行回收。如果層代 0 回收沒有足夠的記憶體,才會執行層代 1 回收,再執行層代 2 回收,層代 1 回收之後有存留的物件,會提升至層代 2。
層代 2
存留較長的物件。層代 2 回收存留的物件還是回留在層代 2。
最後結論就是,假如不在一開始就把物件釋放掉,最後存留至層代 1、2 時,要回收物件的時間就會越來越久,造成的記憶體效率不佳,所以要手動釋放掉物件。
4. 使用 Dispose 釋放資源,而不是 Finalizer
做法 12
偏好成員初始化程序而非指派陳述
為什麼 initobj 會導致 box、unbox?
initobj 指令用於將值類型的變量初始化為其默認值,因此 initobj 不會導致 boxing 或 unboxing。 使用 initobj 時,是直接記憶體操作,不涉及對象的創建或類型的轉換。
推薦用法
public class MyClass
{
private List<string> labels = new List<string>();
}
做法 13
對靜態類別成員進行適當的初始化
Singleton 初始化具有複雜的邏輯,可以在 static
建構子中寫。
public class MySingleton
{
private static readonly MySingleton instance = new MySingleton();
public static MySingleton Instance => instance;
private MySingleton() { }
}
public class MySingleton2
{
private static readonly MySingleton2 instance;
static MySingleton2()
{
instance = new MySingleton2();
}
public static MySingleton2 Instance => instance;
private MySingleton2() { }
}