託管資源:通常是指被CLR(公共語言運行庫)控制的內存資源,這些資源由CLR來管理。能夠認爲是.net 類庫中的資源。數據庫
非託管資源:不受CLR控制和管理的資源。數組
對於託管資源,GC負責垃圾回收。對於非託管資源,GC能夠跟蹤非託管資源的生存期,可是不知道如何釋放它,這時候就要人工進行釋放。安全
2. 後臺內存管理服務器
介紹給變量分配內存時在計算機的內存中發生的狀況網絡
(1) 值數據類型:架構
(2) 引用數據類型:函數
void DoWork() { Customer arabel; // 在棧上給這個應用分配存儲空間,但僅是一個引用,佔用4個字節的空間,而不是實際的Customer對象。 arabel = new Customer(); // 首先分配堆上的內存,以存儲Customer對象;再把變量arabel的值設置爲分配給新Customer對象的內存地址。 // Customer實例沒有放在棧中,而是放在堆中 // 與棧不一樣,堆上的內存是向上分配的
//------------------------------------------------------------------ Customer otherCustomer2 = new EnhancedCustomer(); //用一行代碼在棧上爲otherCustomer2引用分配空間,同時在堆上爲EnhancedCustomer對象分配空間。 }
(3) 垃圾回收性能
3. 強引用和弱引用優化
//建立一個DataObject,並傳遞構造函數返回的弱引用 var myWeakReference = new WeakReference(new DataObject()); if (myWeakReference.IsAlive) { DataObject strongReference = myWeakReference.Target as DataObject; if (strongReference != null) { //使用強引用對象 strongReference } } else { // 引用不可用 }
4. 處理非託管的資源ui
(1) 析構函數或終結器
(2) IDisposable接口:推薦使用,爲釋放非託管的資源提供了肯定的機制,精確控制什麼時候釋放資源。
SqlConnection conn = null; try { conn = new SqlConnection(); //do something; } finally { conn?.Dispose(); }
using(SqlConnection conn = new SqlConnection()) { //do something; }
(3) 雙重實現:正確調用Dispose(),同時將析構函數做爲一種安全機制。
public class BaseResource : IDisposable { private IntPtr _handle; // 句柄,屬於非託管資源 private System.ComponentModel.Component _comp; // 組件,託管資源 private bool _isDisposed = false; // 是否已釋放資源的標誌 //實現接口方法 //由類的使用者,在外部顯示調用,釋放類資源 public void Dispose() { Dispose(true);// 釋放託管和非託管資源 // 將對象從垃圾回收器鏈表中移除, // 從而在垃圾回收器工做時,只釋放託管資源,而不執行此對象的析構函數 GC.SuppressFinalize(this); } //由垃圾回收器調用,釋放非託管資源 ~BaseResource() { Dispose(false);// 釋放非託管資源 } //參數爲true表示釋放全部資源,只能由使用者調用 //參數爲false表示釋放非託管資源,只能由垃圾回收器自動調用 //若是子類有本身的非託管資源,能夠重載這個函數,添加本身的非託管資源的釋放 //可是要記住,重載此函數必須保證調用基類的版本,以保證基類的資源正常釋放 protected virtual void Dispose(bool disposing) { if (!this._isDisposed)// 若是資源未釋放 這個判斷主要用了防止對象被屢次釋放 { if (disposing) { // 釋放託管資源,調用其Dispose方法 _comp.Dispose(); } // 釋放非託管資源 closeHandle(_handle); _handle= IntPtr.Zero; } this._isDisposed = true; // 標識此對象已釋放 } }
5.不安全的代碼:C#直接訪問內存
(1) 用指針直接訪問內存:
(2) 用unsafe關鍵字編寫不安全的代碼
void MyMethod() { // code that doesn't use pointers unsafe { // unsafe code that uses pointers here } // more 'safe' code that doesn't use pointers }
(3) 指針的語法
(4) 將指針強制轉換爲整數類型
(5) 指針類型之間的強制轉換
(6) void指針
(7) 指針算術運算
(8)sizeof運算符:肯定各類數據類型的大小。
sizeof(char) = 2; sizeof(bool) = 1;
(9)結構指針:指針成員訪問運算符
// 結構 struct MyStruct { public long X; public float F; } // 結構指針 MyStruct* pStruct; // 初始化 var myStruct = new MyStruct(); pStruct = &myStruct; // 經過指針訪問結構的成員值 (*pStruct).X = 4; (*pStruct).F = 3.4f; // 使用成員訪問運算符 pStruct->X = 4; pStruct->F = 3.4f; //指針指向結構中一個字段 long* pL = &(pStruct->X); float* pF = &(pStruct->F);
(10) 類成員指針
(11)使用指針優化性能:建立基於棧的數組。
int size; size = 20; double* pDoubles = stackalloc double[size];
6.平臺調用
// C++ 調用Windows API(kernel32.dll)中CreateHardLink BOOL CreateHardLink( LPCTSTR lpFileName, LPCTSTR lpExistingFileName, LPSECURITY_ATTRIBUTES lpSecurityAttributes ); // C# 調用CreateHardLink [DllImport("kernel32.dll", SetLastError="true", EntryPoint="CreateHardLink", CharSet=CharSet.Unicode)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool CreateHardLink(string newFileName, string existingFilename, IntPtr securityAttributes);