標籤:io os ar 使用 strong sp on 問題 cti
前言
這本書這幾年零零散散讀過兩三遍了,作為經典書籍,應該重複讀反覆讀,既然我現在開始寫博了,我也準備把以前覺得經典的好書重讀細讀一遍,並且將筆記整理到部落格中,好記性不如爛筆頭,同時也在寫的過程中也可以加深自己理解的深度,當然同時也和技術社區的朋友們共用
事件
- 事件的本質
- 初始化為null的私人委託欄位
- 封裝add_Event和remove_Event方法
- add_Event和remove_Event的可訪問性同Event欄位的可訪問性,包括virtual和static修飾
- 事件的編碼建議
- 使用virtual void OnXXX來定義事件的調用
- 如果對象向事件註冊一個方法,對象便不可記憶體回收。所以最好在dispose中登出事件
- 事件調用的最佳化過程
- if(Event!=null) Event(this,e); 事件變數的線程競態問題
- 複製到臨時變數, EventHandler<EventArgs> temp = Event; if(temp!=null) temp(this, e)
- 以上代碼可能會被內聯代碼最佳化掉,所以保險一點,考慮下一條
- EventHandler<EventArgs> temp = Interlocked.CompareExchange(ref Event, null, null); if(temp!=null) temp(this, e);
- 試圖刪除一個從未添加過的方法,Delegate的Remove方法內部不做任何事情
- add和remove方法用安全執行緒的一個已知的模式更新一個值
- 手動實現事件封裝器的關鍵在於,使用容器儲存鍵和委託列表 Dictionary<EventKey, Delegate> m_events
- EventHandler<T>在老版本中T約束為EventArgs,新版本去除了此種約束
- 允許顯式定義事件 EventHandler<T> Handler { add { events += value; } remove{ events -= value;} }
- 事件預設同步執行委託列表,並且任何一個委託出現異常會終止執行
泛型
- 開放類型定義的靜態建構函式和靜態欄位,在封閉類型之間不會共用
- 為了緩解代碼爆炸,CLR提供了最佳化
- 編譯器為參考型別的泛型的編譯代碼時可以共用的
- 實值型別則不可以,每個實值型別對應一份不同的JIT編譯代碼
- 泛型介面可以緩解裝箱操作,並且不會喪失類型的安全性。如IEquable泛型介面
- 泛型約束struct不相容可空類型Nullable
協變和逆變
- 協變和逆變泛型型別參數在分配和使用泛型型別方面提供了更大的靈活性
- 利用協變型別參數,可以執行非常類似於普通的多態性的分配
- 通常,協變型別參數可用作委託的傳回型別,而逆變型別參數可用作參數類型
- 對於介面,協變型別參數可用作介面的方法的傳回型別,而逆變型別參數可用作介面的方法的參數
- 泛型介面或泛型委派類型可以同時具有協變和逆變型別參數
- 變體不適用於委託組合
- Func 泛型委派(如 Func<T, TResult>)具有協變傳回型別和逆變參數類型。 Action 泛型委派(如 Action<T1, T2>)具有逆變參數類型
- 實際上數組(只支援object[] = string[] 不支援 object[] = int[]. 實值型別數組沒有協變)和委託方法簽名,已經具備協變和逆變
- 只有在編譯器能驗證類型之間存在一個引用轉換的前提下,才能應用這些可變性
- 由於需要裝箱,實值型別不具備這種可變性。泛型型別針對實值型別不具備可變性
- 對於實參使用out或ref關鍵字的方法,不允許可變性
介面
- 實現介面的方法必須是公用的
- CLR預設將該方法產生為virtual和sealed,如果顯式指定virtual,可以為非密封
- 在一個對象上調用一個介面方法(使用物件類型調用),將調用該方法在該對象的類型中的實現
- 將實值型別轉型為介面類型,會發生裝箱
- 明確介面實作不允許指定可訪問性,自動設為private,調用介面方法必須通過介面類型變數來進行
- EIMI方法不能標記為virtual,所以不能被重寫,因為EIMI方法並非真的是類型物件模型的一部分
- 對於介面泛型約束,C#編譯器會產生特定的IL指令,這些指令導致直接在實值型別上調用介面方法,不對其進行裝箱
- 如果不適用介面約束,就沒有其他方法讓編譯器產生這些IL指令,如此一來,在實值型別上調用介面方法總是會造成裝箱
- 如果繼承多個介面,而介面又有相同名稱和簽名的方法,必須使用顯式介面方法實現
- EIMI只能通過介面調用,並且不能由衍生類別調用。EIMI應該慎用
讀書筆記—CLR via C#章節11-13