.NET 2.0 基礎(chǔ)類庫(kù)中的范型——Functional Programming
發(fā)表時(shí)間:2024-06-15 來源:明輝站整理相關(guān)軟件相關(guān)文章人氣:
[摘要]Functional ProgrammingFunctional Programming 不是一個(gè)新鮮的概念了,例如 C++ 雖然不是一門 Functional Programming 語言,但對(duì)它也有變通的支持——通過使用模板,函數(shù)對(duì)象(Function Objects)和運(yùn)算符重載等手段,ST...
Functional Programming
Functional Programming 不是一個(gè)新鮮的概念了,例如 C++ 雖然不是一門 Functional Programming 語言,但對(duì)它也有變通的支持——通過使用模板,函數(shù)對(duì)象(Function Objects)和運(yùn)算符重載等手段,STL、Boost 等庫(kù)提供了巧妙無比的、高性能的算法和功能。長(zhǎng)久以來似乎 C++ 能實(shí)現(xiàn)的這些特性對(duì)于諸如 Java 和 C# 這些強(qiáng)調(diào)類型安全的面向?qū)ο蟮木幊陶Z言和框架來說是絕緣的,F(xiàn)在,在 CLR 范型和 C# 2.0 匿名委托的支持下,我們也可以構(gòu)造令人吃驚的 Functional Programming 程序了,而且比 C++ 更加簡(jiǎn)單(當(dāng)然性能無法相比,因?yàn)?CLR 中的范型是一種運(yùn)行時(shí)技術(shù),而 C++ 中的模板則是編譯時(shí)技術(shù))。當(dāng)前 .NET BCL 對(duì) Functional Programming 的支持限于集合類,確切說是 List<T> 和 Array。
我們來看一個(gè)簡(jiǎn)單的例子。假設(shè)有一個(gè)聯(lián)系人列表 List<Contact>,聯(lián)系人的定義如下:
class Contact {
public string Name;
...
}
現(xiàn)在我們要把這個(gè)列表中所有聯(lián)系人的姓名拷貝到另外一個(gè)列表。你可能馬上就動(dòng)手寫了出來:
List<Contact> c1 = ...;
List<string> c2 = new List<string>();
foreach (Contact c in c1) {
c2.Add(c.Name);
}
這是一段非常規(guī)矩的 C# 代碼。在 .NET 2.0 中,有了范型和匿名委托,我們可以寫出如下的完成相同功能的實(shí)現(xiàn):
List<Contact> c1 = ...;
List<string> c2 = c1.ConvertAll<string>(
delegate(Contact c) { return c.Name; } );
顯然這段代碼比手工編寫的 foreach 代碼更簡(jiǎn)捷,在表達(dá)意圖方面也顯得更加清楚和直接。其中 ConvertAll 方法是一個(gè)范型方法,作用是將列表元素轉(zhuǎn)換為指定類型的列表。原型為:
List<U> ConvertAll<U>(Converter<T, U> converter);
Converter<T, U> 是一個(gè)范型委托,指定了如何進(jìn)行轉(zhuǎn)換(類似 C++ 中的函數(shù)對(duì)象),原型為(T 為原始類型,U 為目標(biāo)類型):
delegate U Converter<T, U>(T from);
這里只是舉了一個(gè)簡(jiǎn)單的例子,對(duì)于更復(fù)雜的情況,范型和匿名委托允許你用更富想象力的方法去實(shí)現(xiàn)(例如,匿名委托允許你引用棧上的變量)。
下面是 BCL 中的用于Functional Programming的范型委托(位于 System 命名空間中):
原型
描述
delegate bool Predicate<T>(T obj);
訪問集合時(shí),對(duì)指定元素的斷言(true 或 false)
delegate void Action<T>(T obj);
訪問集合時(shí),對(duì)指定元素做出特定動(dòng)作
delegate int Comparison<T>(T x, T y);
比較兩個(gè)元素
delegate U Converter<T, U>(T from);
把一個(gè)元素轉(zhuǎn)換為另外一個(gè),用于在兩個(gè)集合之間拷貝元素
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);
找出第一個(gè)滿足斷言條件的元素的索引
int FindLastIndex(Predicate<T> match);
int FindLastIndex(int index, Predicate<T> match);
int FindLastIndex(int index, int count, Predicate<T> match);
找出最后一個(gè)滿足斷言條件的元素的索引
List<T> FindAll(Predicate<T> match);
找出所有滿足斷言條件的元素
Nullable<T> Find(Predicate<T> match);
找出第一個(gè)滿足斷言條件的元素
Nullable<T> FindLast(Predicate<T> match);
找出最后一個(gè)滿足斷言條件的元素
bool Exists(Predicate<T> match);
判斷滿足斷言條件的元素是否存在
bool TrueForAll(Predicate<T> match);
判斷是否所有的元素都滿足斷言條件
int RemoveAll(Predicate<T> match);
刪除所有滿足斷言條件的元素,返回刪除的元素?cái)?shù)
void ForEach(Action<T> action);
類似 foreach 語句
void Sort(Comparison<T> comparison);
排序
List<U> ConvertAll(Converter<T, U> converter);
轉(zhuǎn)換集合元素
Array 類提供了類似的支持 Functional Programming 的方法,不同之處在于它們都是類方法而非實(shí)例方法,在此限于篇幅不再列舉。下面我們來看看前面那個(gè)例子換成數(shù)組的話是什么樣子:
Contact[] contacts = ...;
string[] names = Array.ConvertAll<Contact, string>(contacts,
delegate(Contact c) { return c.Name; } );