天天看點

[.NET] 《Effective C#》快速筆記(四)- 使用架構

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

[.NET] 《Effective C#》快速筆記(四)- 使用架構

  .NET 是一個類庫,你了解的越多,自己需要編寫的代碼就越少。

目錄

  • 三十、使用重寫而不是事件處理函數
  • 三十一、使用 IComparable<T> 和 IComparer<T> 實作順序關系
  • 三十二、避免使用 ICloneable 接口
  • 三十三、僅用 new 修飾符處理基類更新
  • 三十四、避免重載基類中定義的方法
  • 三十五、PLINQ 如何實作并行算法
  • 三十六、了解 PLINQ 在 I/O 密集場景
  • 三十七、注意并行算法中的異常

  1.處理系統之中觸發的事件:要麼使用事件處理函數,要麼重寫基類中的虛方法。在派生類中,你隻應該重寫虛方法,而事件處理函數則應該使用在對象沒有關系的互動中。

  2.從效率角度,重寫也比事件處理函數更快,事件處理器需要疊代整個請求清單,這樣占用了更多的CPU時間。

  3.但是,事件是在運作時綁定的,是以會帶來更好的靈活性。

  4.一個事件處理器抛出異常,則事件鍊上的其他處理器将不會被調用,而重寫的虛方法則不會出現這種情況。

  5.重寫隻能用于派生類中,其他類型必須使用事件機制。

  1..NET 提供了兩個接口 IComparable<T> 和 IComparer<T> 表示順序關系。IComparable 定義了類型的自然順序,而 IComparer 則表示描述其他順序。

  2.IComparable 接口包含一個方法:CompareTo() 。如果目前對象 < 被比較對象,傳回值 < 0;目前對象 > 被比較對象,傳回值 > 0;兩者相等,傳回 0。

  3.實作非泛型的 IComparable 接口的原因:保證向後相容,反射中使用泛型會加大難度。

  4.實作 IComparable 時請使用顯示接口實作,并提供一個強類型版本的重載,這個強類型的重載能提高性能,并降低使用者誤用 CompareTo 方法的可能。

  1.當對象關系複雜時,深複制會帶來不必要的麻煩。

  2.對于内建類型,如整數,深複制和淺複制的結果一樣。

  3.內建的值類型不需要支援 ICloneable。指派語句就可以複制結構中所有的值,且比 Clone() 更高效;而子類,僅在真正需要複制操作時再添加 ICloneable 支援。

  4.對于值類型,永遠不要實作 ICloneable,直接使用指派操作即可。

  1.new 修飾符必須小心謹慎的使用。如果它是有歧意的,就等于在類上建立了個模糊的方法。

  2.隻有在特殊情況下才使用,那就是更新基類時與你的類産生沖突時。即使在這種情況下,也應該小心的使用它。最重要的是,其它任何時候都不要用它。

  1.為基類中定義的方法建立重載增加了重載解析時的可選項,也就是增加了二義性。很可能你對重載選擇的了解和編譯期的解析并不相同,進而造成了使用者的困惑。解決辦法:選擇不同的名稱,因為這個類是你設計的,自然就可以給出更好,不同的的方法名稱。

  2.不要重載那些定義于基類中的方法,這不能帶來絲毫意義,隻能給使用者平添煩惱,但不針對重寫。

  1.使用時簡單的添加 AsParallel() 即可。

  2.PLNQ 在能夠保證正确性的前提下,讓程式得到多核環境下的性能提升。

  3.需要了解何時資料通路是必須同步的,也需要衡量 ParallelEnumerable 中并行和順序版本方法帶來的影響。

  4.PLINQ 無法并行化 LINQ to SQL 或 EF 的執行,因為這兩樣東西會借助資料庫引擎來執行并行查詢。

  5.每個并行查詢都開始于一個分區的操作,PLINQ 需要對輸入元素分區,然後指派給負責執行查詢的任務。

  6.4 種分區算法:機關分區、區塊分區、條帶分區和散列分區。

  7.3 種其它算法:管道(Pipelining)、停止并進行(Stop&Go)和反向枚舉。

  8.通過在查詢開始時添加 AsParallel() 方法,将查詢表達式轉換成并行執行。

var list = new List<int>();
            var query=list.Where(x=>x<150).Select(x=>x.ToString());

            //并行查詢
            var queryParallel = list.AsParallel().Where(x => x < 150).Select(x => x.ToString());      

var urls = new List<string>();
            foreach (var url in urls)
            {
                var result = new WebClient().DownloadData(url); //發出一個同步的 Web 請求,然後等待接收資料,主要會将時間浪費在等待上
                Console.WriteLine(result);
            }

            //使用并行處理模型
            Parallel.ForEach(urls, url =>
            {
                var result = new WebClient().DownloadData(url);
                Console.WriteLine(result);
            });

            //使用 PLINQ
            var results = from url in urls.AsParallel()
                          select new WebClient().DownloadData(url);
            results.ForAll(Console.Write);      

  1.PLINQ 的執行方式和并行任務庫的 Parallel.ForEach() 不同。PLINQ 使用固定數目的線程,而 Parallel.ForEach() 會調整線程的數量來增加吞吐量。

  2.那些混合了 I/O 密集和 CPU 密集的操作來說,Parallel.ForEach() 更适合。Parallel.ForEach() 會根據目前的負載動态調整線程數量。當很多線程因為等待 I/O 操作而阻塞時,Parallel.ForEach() 會建立更多的線程提高吞吐量。當很多線程都在工作時,Parallel.ForEach() 也會限制活動線程的數量,降低上下文切換的代價。

  3.對于那些需要通路其他計算機,并等待遠端響應的程式來說,并行任務庫和 PLINQ 起到很重要的作用。

  1.背景線程中發生的異常會在不同的方面增加複雜度。異常不能穿過線程邊界保留調用棧,當異常傳遞到開始線程的方法時,線程就會中止。調用線程無法捕獲這個錯誤,也就不能進行對應的處理。

  2.一旦背景線程抛出異常,其它的背景操作也會停止。最好是不要在并行算法中抛出異常。不過其它意料之外的異常也可能會出現。

本系列

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

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

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

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

  《Effective C#》快速筆記(五) - C# 中的動态程式設計

  《Effective C#》快速筆記(六) - C# 高效程式設計要點補充

【部落客】反骨仔

【原文】http://www.cnblogs.com/liqingwen/p/6797709.html 

【GitHub】https://github.com/liqingwen2015/XMind 可以下載下傳 XMind

【參考】《Effective C#》

下一篇: PS常用工具