1、委託:委託本質上就是函數指標,但由於指標過於靈活,因此在很多語言中都採用了更加安全的替代類型,比如Delphi的對象方法和C#的委託.委託使得方法可以做為參數進行傳遞,極大的方便了程式的處理(事件本質上就是委託,是委託的一種典型應用)。使用委託的最大好處一是可以實現演算法上的分離,二是可以實現一定程度上的動態聯編(即物件導向中的所謂多態),對於演算法上的分離,在物件導向的模式設計中,策略模式是比較典型的,其實我們使用委託照樣可以在一定程度上模仿其功能,實際上使用原則模式在很多時候還不如委託來得簡單有效,而且在效能上也比委託差些。由於委託本身也是一種規範和標準,因此在這種層面上和抽象類別,介面一樣具有多態性。當然,委託的這種多態性也必須遵循程式設計語言的繼承規範:子類執行個體可以賦給父類變數,反之則不允許。根據這種規範,站在委託的角度,委託具有傳回值協變,參數抗變的特性。即實際委託調用的傳回值只能是委託定義的傳回值類型的子類,實際調用方法的參數必須是委託定義中的參數的父類。
如: public delegate A Compare(Type1 v);
實際調用的方法:public B CompareInstance(Type2 v).根據繼承規範,Type2必須是Type1的父類,而B必須是A的子類.
2、匿名方法:在給委託變數執行個體化的時候,一般是提供一個有名的方法,如:Compare _compare=CompareInstance;但現在C#提供了一種匿名方法,匿名方法是一個代碼塊,本質上與命名方法沒有什區別,但與命名方法相比,提供了如下兩個便利:1是書寫上,使得委託變數可以與執行個體化方法在一起,這樣有利於理解;2是匿名方法可以訪問匿名方法代碼塊以外的變數,這點上相對於命名方法要靈活很多,這是優點,也是缺點,缺點是其破壞了代碼的封裝性,當然,你把匿名方法與其所在的代碼模組看作是一個整體(如果從邏輯上來講也確實是個整體),那麼這個缺點就無所謂了。下面是簡單的例子:
int theTest=0;
Compare _compare = delegate(int v){
theTest ++;
}
_compare(2);//調用.
匿名方法使用上的限制主要是程式控制方面的,比如不能跳轉到匿名方法塊外部,也不能從外部跳轉到匿名方法塊內部等。由於這種匿名代碼塊並不能複用,因此我覺得匿名方法的實際應用價值並不大,何況還可以用λ運算式替代。
3、λ運算式:λ運算式的作用其實跟匿名方法沒什麼區別,可以將λ運算式理解成匿名方法的一種簡潔表達方式。
匿名方法和λ運算式的引入,主要作用在於可以使得程式的表達更加簡潔,但把這兩個東西作為C#語言一個新的特徵就有那麼一點王婆賣瓜的味道了.其實所謂的範型、匿名方法等很多所謂的C#的新東西都是從C++中拿來重新封裝一下而已,思想上並沒有本質的進步(題外話:我們中國程式員很多時候都是被這種似是而非的新技術驅趕著跑)。
下面是一個簡單的測試例子:
private void button1_Click(object sender, EventArgs e)
{
//Teacher是一個類,包含部門id和姓名兩個欄位.
var teachers = TestDataMgt.GetTeachers();//擷取一個Teacher列表.
//一般方法(委託的典型調用方式),Select需要一個委託參數,該委託的定義:
//Func<TSource,TResult>(TSource obj)
//var depts2 = teachers.Select(new Func<Teacher,int>(FuncB)).Distinct();
#region 使用匿名方法調用.
//Func<Teacher, int> bb = delegate(Teacher T)
//{
// return T._deptId;
//};
//var depts2 = teachers.Select(bb).Distinct();
#endregion
//使用λ運算式,非簡潔方式
//var depts2 = teachers.Select((T) => { return T._deptId; }).Distinct();
//等價於
var depts2 = teachers.Select(T=>T._deptId).Distinct();
foreach (var el in depts2)
{
this.richTextBox2.Text += el.ToString() + "/r/n";
}
}
private int FuncB(Teacher obj)
{
return obj._deptId;
}