.NET 2.0 基礎類庫中的范型——Functional Programming
2024-07-10 12:59:29
供稿:網友
 
 
functional programming
functional programming 不是一個新鮮的概念了,例如 c++ 雖然不是一門 functional programming 語言,但對它也有變通的支持——通過使用模板,函數對象(function objects)和運算符重載等手段,stl、boost 等庫提供了巧妙無比的、高性能的算法和功能。長久以來似乎 c++ 能實現的這些特性對于諸如 java 和 c# 這些強調類型安全的面向對象的編程語言和框架來說是絕緣的。現在,在 clr 范型和 c# 2.0 匿名委托的支持下,我們也可以構造令人吃驚的 functional programming 程序了,而且比 c++ 更加簡單(當然性能無法相比,因為 clr 中的范型是一種運行時技術,而 c++ 中的模板則是編譯時技術)。當前 .net bcl 對 functional programming 的支持限于集合類,確切說是 list<t> 和 array。
我們來看一個簡單的例子。假設有一個聯系人列表 list<contact>,聯系人的定義如下:
 
class contact {
public string name;
...
}
 
現在我們要把這個列表中所有聯系人的姓名拷貝到另外一個列表。你可能馬上就動手寫了出來:
 
list<contact> c1 = ...;
list<string> c2 = new list<string>();
 
foreach (contact c in c1) {
c2.add(c.name);
}
 
這是一段非常規矩的 c# 代碼。在 .net 2.0 中,有了范型和匿名委托,我們可以寫出如下的完成相同功能的實現:
 
list<contact> c1 = ...;
list<string> c2 = c1.convertall<string>(
delegate(contact c) { return c.name; } );
 
顯然這段代碼比手工編寫的 foreach 代碼更簡捷,在表達意圖方面也顯得更加清楚和直接。其中 convertall 方法是一個范型方法,作用是將列表元素轉換為指定類型的列表。原型為:
 
list<u> convertall<u>(converter<t, u> converter);
 
converter<t, u> 是一個范型委托,指定了如何進行轉換(類似 c++ 中的函數對象),原型為(t 為原始類型,u 為目標類型):
 
delegate u converter<t, u>(t from);
 
這里只是舉了一個簡單的例子,對于更復雜的情況,范型和匿名委托允許你用更富想象力的方法去實現(例如,匿名委托允許你引用棧上的變量)。
下面是 bcl 中的用于functional programming的范型委托(位于 system 命名空間中):
 
原型
 描述
 
delegate bool predicate<t>(t obj);
 訪問集合時,對指定元素的斷言(true 或 false)
 
delegate void action<t>(t obj);
 訪問集合時,對指定元素做出特定動作
 
delegate int comparison<t>(t x, t y);
 比較兩個元素
 
delegate u converter<t, u>(t from);
 把一個元素轉換為另外一個,用于在兩個集合之間拷貝元素
 
 
list<t> 提供了如下支持 functional programming 的方法:
 
原型
 描述
 
int findindex(predicate<t> match);
int findindex(int index, predicate<t> match);
int findindex(int index, int count, predicate<t> match);
 找出第一個滿足斷言條件的元素的索引
 
int findlastindex(predicate<t> match);
int findlastindex(int index, predicate<t> match);
int findlastindex(int index, int count, predicate<t> match);
 找出最后一個滿足斷言條件的元素的索引
 
list<t> findall(predicate<t> match);
 找出所有滿足斷言條件的元素
 
nullable<t> find(predicate<t> match);
 找出第一個滿足斷言條件的元素
 
nullable<t> findlast(predicate<t> match);
 找出最后一個滿足斷言條件的元素
 
bool exists(predicate<t> match);
 判斷滿足斷言條件的元素是否存在
 
bool trueforall(predicate<t> match);
 判斷是否所有的元素都滿足斷言條件
 
int removeall(predicate<t> match);
 刪除所有滿足斷言條件的元素,返回刪除的元素數
 
void foreach(action<t> action);
 類似 foreach 語句
 
void sort(comparison<t> comparison);
 排序
 
list<u> convertall(converter<t, u> converter);
 轉換集合元素
 
 
array 類提供了類似的支持 functional programming 的方法,不同之處在于它們都是類方法而非實例方法,在此限于篇幅不再列舉。下面我們來看看前面那個例子換成數組的話是什么樣子:
 
contact[] contacts = ...;
string[] names = array.convertall<contact, string>(contacts, 
delegate(contact c) { return c.name; } );