天天看點

C# Lambda表達式

自C#3.0開始,就可以使用一種新文法把實作代碼賦予委托:Lambda表達式。隻要有委托參數類型的地方,就可以使用Lambda表達式。

Lambda表達式的文法比匿名方法簡單。如果所調用的方法有參數,且不需要參數,匿名方法的文法就比較簡單,因為這樣不需要提供參數。

直接上一些例子,讀者可以自行運作調試。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

<code>static</code> <code>void</code> <code>Main(</code><code>string</code><code>[] args)</code>

<code>{</code>

<code>    </code><code>//1、lambda之hello world.</code>

<code>    </code><code>Func&lt;</code><code>string</code><code>, </code><code>string</code><code>&gt; lambda = param =&gt;</code>

<code>    </code><code>{</code>

<code>        </code><code>return</code> <code>param;</code>

<code>    </code><code>};</code>

<code>                                                                          </code> 

<code>    </code><code>Console.WriteLine(lambda(</code><code>"hello lambda."</code><code>));</code>

<code>    </code><code>//2、lambda之參數</code>

<code>    </code><code>Func&lt;</code><code>double</code><code>, </code><code>double</code><code>, </code><code>double</code><code>, </code><code>double</code><code>&gt; cube = (</code><code>double</code> <code>x, </code><code>double</code> <code>y, </code><code>double</code> <code>z) =&gt; x * y * z;</code>

<code>    </code><code>Console.WriteLine(cube(1, 2, 3));</code><code>//輸出6</code>

<code>    </code><code>//更進一步,參數的類型可以省略</code>

<code>    </code><code>Func&lt;</code><code>double</code><code>, </code><code>double</code><code>, </code><code>double</code><code>, </code><code>double</code><code>&gt; cude1 = (x, y, z) =&gt; x * y * z;</code>

<code>    </code><code>Console.WriteLine(cude1(2, 4, 6));</code><code>//輸出48</code>

<code>    </code><code>//3、lambda之調用外部參數</code>

<code>    </code><code>int</code> <code>someValue = 4;</code>

<code>    </code><code>Func&lt;</code><code>double</code><code>, </code><code>double</code><code>, </code><code>double</code><code>, </code><code>double</code><code>&gt; f = (x, y, z) =&gt; x + y + z + someValue;</code>

<code>    </code><code>Console.WriteLine(f(1, 2, 3));</code><code>//1+2+3+4=10</code>

<code>}</code>

在winform程式設計中,我們經常給某個按鈕添加Click事件,最原始的寫法是直接輕按兩下按鈕,生成Click事件的代碼,我們就可以直接在裡面寫方法了。其實這是vs替我們做了很多工作,其中就有在designer.cs檔案中,生成了 this.button1.Click += new System.EventHandler(this.button1_Click);這樣的代碼,事件要注冊才能觸發。

我們采用匿名委托的寫法,在窗體的Form_Load事件中添加如下代碼,則可以觸發button1的Click事件。

<code>this</code><code>.button1.Click += </code><code>delegate</code><code>(</code><code>object</code> <code>ss, EventArgs ee)</code>

<code>    </code><code>MessageBox.Show(</code><code>"hello,this is button1.Click event..."</code><code>);</code>

<code>};</code>

再看看Lambda表達式的用法。

<code>this</code><code>.button1.Click += (ss, ee) =&gt;</code>

是不是更加簡潔?

我們再看一下,從匿名方法到Lambda簡寫的演化過程,借一張圖。

C# Lambda表達式

從這個演化過程,可以看出C#語言的發展變化過程。

下面詳細示範一下Lambda的應用執行個體。

首先第一個執行個體我們應用Lambda對一個List&lt;Student&gt;清單進行循環、查找、排序等操作。

首先我們提供一個實體類:

<code>public</code> <code>class</code> <code>Student</code>

<code>    </code><code>public</code> <code>Student(</code><code>string</code> <code>name, </code><code>int</code> <code>age)</code>

<code>        </code><code>this</code><code>.Name = name;</code>

<code>        </code><code>this</code><code>.Age = age;</code>

<code>    </code><code>}</code>

<code>                                              </code> 

<code>    </code><code>public</code> <code>string</code> <code>Name { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

<code>    </code><code>public</code> <code>int</code> <code>Age { </code><code>get</code><code>; </code><code>set</code><code>; }</code>

然後我們初始化一個List,

<code>//初始化3個Student對象</code>

<code>var</code> <code>students = </code><code>new</code> <code>List&lt;Student&gt;()</code>

<code>    </code><code>new</code> <code>Student(</code><code>"zhang3"</code><code>,18),</code>

<code>    </code><code>new</code> <code>Student(</code><code>"li4"</code><code>,22),</code>

<code>    </code><code>new</code> <code>Student(</code><code>"wang5"</code><code>,20)</code>

<code>//定義1個列印函數</code>

<code>Action&lt;Student&gt; print = student =&gt; Console.WriteLine(</code><code>string</code><code>.Concat(student.Name, </code><code>":"</code><code>, student.Age));</code>

那麼,我們就可以先循環輸出一下:

<code>students.ForEach(print);</code><code>//循環列印輸出</code>

如果我們要找到年齡大于20歲的學生,可以這樣:

<code>students.FindAll(student =&gt; student.Age &gt; 20).ForEach(print);</code>

進一步,我們按照學生的年齡進行排序:

<code>students.Sort((f1, f2) =&gt; f1.Age.CompareTo(f2.Age));</code>

<code>students.ForEach(print);</code><code>//年齡從小到大排序後輸出</code>

現在,我們按照在students清單裡再加一個學生:

<code>    </code><code>new</code> <code>Student(</code><code>"wang5"</code><code>,20),</code>

<code>    </code><code>new</code> <code>Student(</code><code>"zhao6"</code><code>,20)</code>

現在要按照年齡進行分組,并統計出各個年齡階段的人數:

<code>var</code> <code>result = students.GroupBy(x =&gt; x.Age).Select(x =&gt; </code><code>string</code><code>.Concat(x.Key, </code><code>":"</code><code>, x.Count()));</code><code>//先進行分組,再進行投影</code>

<code>result.ToList().ForEach(x =&gt; Console.WriteLine(x.ToString()));</code><code>//循環輸出得到結果</code>

再提供一個綜合性的例子,這是論壇裡的caozhy版主提供的一個例子。用Lambda表達式實作快速排序。

<code>Func&lt;Func&lt;</code><code>int</code><code>, </code><code>int</code><code>, </code><code>bool</code><code>&gt;, Func&lt;</code><code>int</code><code>[], </code><code>int</code><code>[]&gt;&gt; filter = x =&gt; </code><code>new</code> <code>Func&lt;</code><code>int</code><code>[], </code><code>int</code><code>[]&gt;(y =&gt; y.Skip(1).Where(z =&gt; x(y[0], z)).ToArray());</code>

<code>Func&lt;</code><code>int</code><code>[], </code><code>int</code><code>[]&gt; qsort = x =&gt; x;</code>

<code>Func&lt;</code><code>int</code><code>[], </code><code>int</code><code>[]&gt; lesser = dt =&gt; filter((x, y) =&gt; y &lt; x)(dt);</code>

<code>Func&lt;</code><code>int</code><code>[], </code><code>int</code><code>[]&gt; greater = dt =&gt; filter((x, y) =&gt; y &gt;= x)(dt);</code>

<code>       </code> 

<code>qsort = dt =&gt; dt.Length &gt; 1</code>

<code>    </code><code>? qsort(lesser(dt)).Concat(</code><code>new</code> <code>int</code><code>[] { dt[0] }).Concat(qsort(greater(dt))).ToArray() : dt;</code>

<code>int</code><code>[] data = { 4, 3, 1, 4, 6, 7, 5, 9, 3, 11, 1, 2, 11 };</code>

<code>var</code> <code>result = qsort(data);</code>

<code>result.ToList().ForEach(x =&gt; Console.WriteLine(x.ToString()));</code><code>//排完序後輸出</code>

本文轉自 guwei4037  51CTO部落格,原文連結:http://blog.51cto.com/csharper/1344193