1. 程式人生 > >[.NET] 《Effective C#》快速筆記 - C# 高效編程要點補充

[.NET] 《Effective C#》快速筆記 - C# 高效編程要點補充

擔心 cti 四十六 catch con 影響 ted 註冊 ref

《Effective C#》快速筆記 - C# 高效編程要點補充

目錄

  • 四十五、盡量減少裝箱拆箱
  • 四十六、為應用程序創建專門的異常類
  • 四十七、使用強異常安全保證
  • 四十八、盡量使用安全的代碼
  • 四十九、實現與 CLS 兼容的程序集
  • 五十、實現小尺寸、高內聚的程序集

  這是這一系列的最後一篇。

四十五、盡量減少裝箱拆箱

  1. 值類型是數據的容器,不支持多態。
  2. 裝箱把一個值類型放在一個未確定類型的引用對象中,讓該值作為引用類型所使用。拆箱指從引用類型的位置取出值的一個副本。
  3. 裝箱拆箱都是比較影響性能的手段,應該盡可能的避免裝拆箱操作。
  4. 泛型可以避免裝拆箱操作。
  5. 值類型裝箱是隱式的,難以發現,需要自己多加註意。

四十六、為應用程序創建專門的異常類

  1.只有你覺得使用者會使用不同的形式去處理錯誤時,才應該創建不同的異常類。

  2.自定義的異常類應該以“Exception”結尾,並且繼承 System.Exception 或其他異常類。不過你也需要適當地包含該基類中的構造函數,內容直接交給基類實現即可。

    /// <summary>
    /// 自定義的異常類
    /// </summary>
    public class MyException : Exception
    {
        
public MyException() : base() { } public MyException(string s) : base(s) { } public MyException(string s, Exception e) : base(s, e) { } protected MyException(SerializationInfo info, StreamingContext cxt) : base
(info, cxt) { } }

  3.在拋出你自定義的異常時,應該將原始的異常存放在 InnerException 屬性中,這樣就可以顯示足夠友好,並且信息豐富的異常:

        public void Do()
        {
            try
            {
                //DoException();
            }
            catch (DoException e)
            {
                var msg = $"該問題是博主故意引起的";
                throw new MyException(msg, e);
            }
        }

  4.只有在存在不同類型的恢復操作時,才應該拋出不同類型的異常,定義異常類時,還要提供基類中支持的所有構造函數。此外,不要忘記使用 InnerException 屬性來保存低層次的異常信息。

四十七、使用強異常安全保證

  1.Dave Abrahams 定義了 3 種安全異常來保證程序:基礎保證、強保證,以及無拋出保證。

  2.強異常保證:如果一個操作因為某個異常中斷,程序將維持原狀態不變,操作要麽徹底完成,要麽就不會修改程序的任何狀態。強異常保證的好處:任何時候若是捕獲了異常,所有將要嘗試的正常操作都不繼續進行,也就是不會繼續進行修改。程序當前的狀態如尚未開始進行該操作一樣。

四十八、盡量使用安全的代碼

  1. .NET 運行時可以保證一些懷有而已的代碼不能直接滲透到遠程計算機上執行。
  2. CLR 中的一些代碼訪問安全設置,如:CLR 強制要求基於角色的安全認證,這樣才能判斷某些代碼能否在基於一個特定的角色賬號下運行。
  3. CLR 可以檢查 IL 代碼,確保它不存在潛在的危險行為。如:直接訪問原始內存。
  4. 如果代碼不需要任何的安全權限,就不需要使用 CAS 的 API 來判斷訪問權限,因為這樣只會影響性能,額外增加 CLR 的工作量。
  5. 你可以使用 CAS 的 API 來訪問一些受保護的資源,一般需要額外的權限。如非托管的內存和文件系統、註冊表等。
  6. 一般來說,我們編寫的 C# 代碼都是安全的,除非你使用了 /unsafe。
  7. 應該盡可能地避免訪問非托管內存。確實有需要的話,應該將其隔離在獨立的程序集中。

四十九、實現與 CLS 兼容的程序集

  1..NET 運行環境與語言無關,我們創建的程序集必須與 CLS 保持兼容,這樣才能保證其他的開發人員可以用另一種語言來調用你的組件。

五十、實現小尺寸、高內聚的程序集

  1. 如果我們都將所有的代碼放在一個程序集中,這不利於組件的重用,也不利於系統的局部更新,若是可以將其拆分成小程序集,以組件的形式進行重用,就可以從一定程度上簡化後續的開發工作。
  2. 我們用類進行功能的封裝和數據的存儲,只有公有的類、結構和接口才應該稱為契約,被其它用戶(或程序集)進行訪問。
  3. 建議將程序拆分成多個程序集,把相關的類型放在同一個程序集中。
  4. 一個程序集應該是一個包含相關功能的,具有良好組織的一個庫。如果不知道怎樣的顆粒度最好,可以略微向小而多的方向傾斜。
  5. 如果所有參數和返回值都是接口,那麽任何一個程序集都可以很容易地用另一個實現了相同接口的程序集進行代替。
  6. 更小的程序集同樣可以降低程序啟動時的開銷。更大的程序集要花上更多的 CPU 時間來加載,且需要更多的時間來將必須的 IL 編譯成機器指令。雖然只有啟動時將被調用的代碼會被 JIT 編譯,但程序集是整體載入的。
  7. 在跨越程序集時,安全性檢查會成為一個額外的開銷。程序跨越程序集的次數越小,其執行效率越高。
  8. 性能的損耗對我們來說可以忽略不計,因為在開發時,我們著重的是代碼的靈活度,所以不要擔心將大程序集拆分成小程序集的性能問題。
  9. 常見的程序集:小且僅專註於某個特定功能的程序集,大一些但包含通用功能的程序集,無論何種情況,都應該保證其盡可能合理的小,但不應該過度。

本系列

  《Effective C#》快速筆記(一)- C# 語言習慣

  《Effective C#》快速筆記(二)- .NET 資源托管

  《Effective C#》快速筆記(三)- 使用 C# 表達設計

  《Effective C#》快速筆記(四) - 使用框架

  《Effective C#》快速筆記(五) - C# 中的動態編程

[.NET] 《Effective C#》快速筆記 - C# 高效編程要點補充