首頁>技術>

上一篇《C#中多執行緒的那點事-Parallel》,我們講述了一種全新的資料並行處理方法Parallel,Parallel也是 TPL(Task Parallel Library)提供的一個類。其提供的Invoke可以非常方便的開啟並行任務;For,Foreach可以非常方便的對大量資料進行並行處理。

小明同學,昨天回家練習了Parallel的使用,不禁感嘆,C#真的是處處為開發者著想。當你覺得程式碼囉嗦複雜的時候,也許應該去查一查有沒有用C#更簡單的實現方法!

我告訴小明,聽了今天的課程,以前那些簡單方法,都是小兒科!

小明聽了我這話之後,兩眼放光,彷彿在說,那你還不開始。。。

基礎補充

在正式開始之前,我們先簡單說一下C#中的擴充套件方法。這是一種可以給類和介面,動態新增擴充套件函式的機制。利用擴充套件方法,可以在不改變已有程式碼的前提下,擴充套件類和介面的功能。

如果已經瞭解了C#的擴充套件函式的同學,可以直接跳到下一節。

先看個簡單的例項:

// 集合擴充套件類public static class ListExt{    // 計算集合平均值    public static int Avg(this List<int> list)    {        int sum = 0;        foreach (var l in list)        {            sum += l;        }        return sum / list.Count;    }}

注意,以上的ListExt類,有3個特點:

ListExt是一個staitc類函式Avg是一個static函式Avg的引數list前面,添加了this關鍵字

沒錯,以上3點,就是C#中的擴充套件函式的基本語法。這樣我們在不修改List這個類原有程式碼的情況下,給List<int>添加了一個Avg函式,來計算集合中全部資料的平均值。

我們這裡為了簡單起見,先不考慮模板和計算溢位。

另外,我們看到擴充套件函式,實質上還是一個靜態的函式,在擴充套件函式中,也只能訪問原來的類的公有成員。

那這個Avg函式如何使用呢:

class Program{    static void Main(string[] args)    {        Console.WriteLine("Hello LINQ World!");        var list = new List<int>();        for (int i = 0; i < 100; i++)        {            list.Add(i);        }        var avg = list.Avg();        Console.WriteLine($"Average: {avg}");    }}

可以看到,和使用List<int>的其他函式一模一樣。

其實擴充套件函式,就是利用靜態函式,包裝的一種語法糖,方便我們更直觀的使用。這種操作看似平淡無奇,但是在微軟的加持下,就發揮出了無窮的威力。請接著往下看。

LINQ

集合,包括List,Dictionary,HashSet等,是我們日常程式設計中使用最廣泛的資料結構。而這些類本身,雖然是泛型的,支援各種資料的集合。但其本身提供的功能函式有限。

就比如前文的求平均值的功能,我們每次都要編寫一次迴圈,或者需要封裝輔助類。程式碼冗餘,使用不直觀。

微軟在程式語言方面,確實是處處為程式設計師著想,他們早就注意到了這個問題。也給出了他們的解決方案,就是LINQ。

LINQ是一組基於C#擴充套件函式實現的通用集合處理函式合集。其中包括了大多數對於集合的常規操作:

元素訪問函式,比如First,Last,ElementAt,Single,FirstOrDefault統計相關函式,比如Average,Min,Max,Sum,Aggregate(聚合,很好用)邏輯判斷函式,比如All,Any,Contains,SequenceEqual(判斷集合相等)集合操作函式,比如Select,Where,Append,OrderBy,Concat,Distinct,Except,Intersect,Join,Reverse,Union分組變換函式,比如ToDictionary,ToLookup,ToHashSet,GroupBy騷操作函式,比如Cast,OfType,Empty,Prepend,Range,Repeat,ThenBy,Zip

以上是常用的集合相關函式,還有一些不常用的函式,就不一一列舉了。總之有一點,有了這些函式,我們操作集合會方便太多,效率大增。絕對是乾貨LINQ就是傳說中的那種用過之後就回不去的API合集

這些特性,在其他程式語言看來一定是這樣的:

這TM絕對是來搗亂的

我看了一眼小明,躍躍欲試的樣子,像極了當年的我!

PLINQ

今天的內容有點多,我讓大家休息了一會,消化消化。沒過一會,小明來找我說道:

老師,LINQ中的操作是並行的嗎?

不得不說,小明學習多執行緒是有點著魔了,不過我非常喜歡他這個狀態。

LINQ的操作,是序列的。不過微軟當然也想到了小明的這個需求,於是他們又搞了一個PLINQ。

PLINQ就是並行的LINQ的意思。其API基本和LINQ相同,微軟對PLINQ的介紹,也說PLINQ是LINQ的並行替代實現。

來看一個簡單的PLINQ的例項程式:

static void Main(string[] args){    Console.WriteLine("Hello PLINQ World!");    var list = new List<int>();    for (int i = 0; i < 10; i++)    {        list.Add(i);    }    var plist = list.AsParallel();    var avg = plist.Average();    Console.WriteLine($"PLINQ Average: {avg}");    plist.ForAll(l =>     {        Console.WriteLine($"value: {l}, " +            $"tid: {Thread.CurrentThread.ManagedThreadId}");    });}

程式中透過PLINQ的AsParallel函式,將普通的集合,轉換為一個並行的集合。程式輸出如下:

PLINQ並行遍歷集合

從結果中可以看出,PLINQ的並行遍歷集合,和ThreadPool及Parallel執行的機制相同。但是PLINQ的功能要強大得多。

看到這裡,相信你一定已經被C#的魅力所吸引。這也是C#在程式語言中,可以一直排在前5的原因之一。

TOIOBE排行2020-10

佈置作業

練習PLINQ的使用。

聰明的小明

踩坑記錄

暫無

下期預告

下面是給同學們準備的乾貨,正在陸續發貨中哦:

await/async

17
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 【20201002】MongoDB安裝筆記