匿名方法,Lambda表達式,高階函數

 

  • 匿名方法

c#2.0引入匿名方法,沒必要建立單獨的方法,所以減小了所需的編碼系統開銷。 經常使用於將委託和匿名方法關聯,例如
1. 使用委託和方法關聯:java

this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
private void btnRefresh_Click(object sender, EventArgs e)
{
    BindData();
}c#

2. 使用委託和匿名方法關聯:
this.btnRefresh.Click +=  delegate(object sender, EventArgs e) { BindData(); };
毫無疑問,若是關聯的方法是「一句話方法」的話,代碼2更爲簡潔(實際上編譯器在背後爲咱們建立了相似btnRefresh_Click的方法)。數組

  • 匿名方法省略參數列表

定義匿名方法時候,參數列表是能夠省略的,編譯器能夠根據委託的簽名來肯定函數的簽名。例如,
delegate void Func(int x);
//帶參數
Func f1= delegate (int p) { Console.Write(p); }
// 不帶參數
Func f2 = delegate { Console.Write("he");} //編譯器自動推斷函數簽名帶int參數
使用不帶參數的匿名方法,注意問題
   一是由於沒有參數,因此在方法內就不能使用參數。
    二是有些狀況不能使用匿名方法,有ambiguous的問題,例如
public Thread(ParameterizedThreadStart start);
public Thread(ThreadStart start);
而// public delegate void ParameterizedThreadStart(object obj);
   // public delegate void ThreadStart();
因此使用
Thread thread = new Thread(
                delegate { sh.LockMyself(); }
            );
就會有問題
Error  The call is ambiguous between the following methods or properties: 'System.Threading.Thread.Thread(System.Threading.ThreadStart)' and 'System.Threading.Thread.Thread(System.Threading.ParameterizedThreadStart)'
編譯器不知道應該將delegate { }這一匿名方法還原爲哪一個函數,解決方法是顯式給定參數列表,讓編譯器知道你要用那個函數:
Thread thread = new Thread(
                delegate() { sh.LockMyself(); }
            );
Lambda表達式:
Thread thread = new Thread(
           () =>
           {
                sh.LockMyself();
            }
           );安全

  • Lambda表達式

Lambda表達式爲編寫匿名方法提供了更簡明的函數式的句法,但結果卻在編寫LINQ查詢表達式時變得極其有用,由於它們提供了一個很是緊湊的並且類安全的方式來編寫能夠看成參數來傳遞,在之後做運算的函數。
Lambda 表達式和 匿名方法 實際上是一件事情。惟一的不一樣是:他們語法表現形式不一樣。Lambda 表達式是在語法方面的更進一步的進化。在本質上,他們是一件事情。他們的做用都是:產生方法。即:內聯方法。
books是System.Collections.Generic.List類型, 即List<Book>, 有Find方法
使用匿名方法:              books.Find(delegate(Book book){return book.Price < 50;});
使用Lambda表達式:      books.Find(book=>book.Price<50);
book是輸入參數; =>讀做Go to,是Lambda操做符;book.Price<50是表達式或者語句塊。
Lambda表達式中的輸入參數省略參數類型,由於當前Find擴展方法對象是books,編譯器會自動推斷book參數屬於BooK類型.
對比另外一個例子:ruby

複製代碼

// 使用匿名方法
string[] list = new string[] { "abc", "12", "java" };
string[] alist = Array.FindAll(list,
delegate(string s)
                      {
return s.IndexOf("a") >= 0;
                      }
                 );
foreach (string var in alist)
{
Console.WriteLine(var);
}
// 使用Lambda表達式
string[] list = new string[] { "abc", "12", "java" };
string[] alist = Array.FindAll(list, s => (s.IndexOf("a") >= 0)); 函數

複製代碼

Lambda表達式式範例:this

複製代碼

//x的類型省略了,編譯器能夠根據上下文推斷出來,後面跟着的是表達式
x => x+1
deleage(int x){return x+1;}
//後面跟着的是語句塊
x=>{return x+1;}
delegate(int x){return x+1;}
//輸入參數也能夠帶類型,帶類型後別忘記小括號哦
(int x) => x+1
delegate(int x){return x+1;}
//也能夠多個輸入參數,逗號分隔,別忘記小括號
(x,y) => x+y
delegate(int x,int y){return x+y;}
//無參的也行
() => 1
delegate(){return 1;}編碼

複製代碼

高階函數(higher-order function)spa

是指把另外一個函數做爲參數或返回值的函數。
例如在System.Array類中就有許多靜態的高階函數,其中的ConvertAll方法可謂是最經常使用的高階函數之一了: .net

複製代碼

private static DateTime StringToDateTime(string s) {
return DateTime.ParseExact(s, "yyyy-MM-dd", null);
}
static void Main(string[] args) {
string[] dateStrings = new string[] {
"2009-01-01", "2009-01-02", "2009-01-03",
"2009-01-04", "2009-01-05", "2009-01-06",
};
// ConvertAll將一個數組映射爲另外一個數組, new Converter是構建一個委託對象
// 相似於 new System.EventHandler(this.btnRefresh_Click);
DateTime[] dates = Array.ConvertAll<string, DateTime>(
dateStrings, new Converter<string, DateTime>(StringToDateTime));
}
// C# 2.0中,又引入了匿名方法這一構建委託對象的方式:
DateTime[] dates = Array.ConvertAll<string, DateTime>(
dateStrings,
delegate(string s) {
return DateTime.ParseExact(s, "yyyy-MM-dd", null);
});
// 新增了Lambda表達式和擴展方法等語言特性,再加上範型類型的自動判斷,在C# 3.0中使用匿名方法更是異常簡潔,甚至與ruby的語法一模一樣
IEnumerable<DateTime> dates = dateStrings.Select(
s => DateTime.ParseExact(s, "yyyy-MM-dd", null));

複製代碼

Reference
http://blog.csdn.net/shouyenet1/archive/2009/04/28/4133114.aspx
http://blog.joycode.com/scottgu/archive/2007/04/09/100744.aspx
http://www.infoq.com/cn/articles/higher-order-function
http://www.infoq.com/cn/articles/higher-order-function

相關文章
相關標籤/搜索