.NET 2.0 基础类库中的范型——Functional Programming

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

  1<t> 和  Array  。 
  2
  3我们来看一个简单的例子。假设有一个联系人列表  List<contact> ,联系人的定义如下: 
  4
  5class Contact { 
  6
  7public string Name; 
  8
  9... 
 10
 11} 
 12
 13现在我们要把这个列表中所有联系人的姓名拷贝到另外一个列表。你可能马上就动手写了出来: 
 14
 15List<contact> c1 = ...; 
 16
 17List<string> c2 = new List<string> (); 
 18
 19foreach (Contact c in c1) { 
 20
 21c2.Add(c.Name); 
 22
 23} 
 24
 25这是一段非常规矩的  C#  代码。在  .NET 2.0  中,有了范型和匿名委托,我们可以写出如下的完成相同功能的实现: 
 26
 27List<contact> c1 = ...; 
 28
 29List<string> c2 = c1.ConvertAll<string> ( 
 30
 31delegate(Contact c) { return c.Name; } ); 
 32
 33显然这段代码比手工编写的  foreach  代码更简捷,在表达意图方面也显得更加清楚和直接。其中  ConvertAll  方法是一个范型方法,作用是将列表元素转换为指定类型的列表。原型为: 
 34
 35List<u> ConvertAll<u>(Converter<t, u=""> converter); 
 36
 37Converter<t, u=""> 是一个范型委托,指定了如何进行转换(类似  C++  中的函数对象),原型为(  T  为原始类型,  U  为目标类型): 
 38
 39delegate U Converter<t, u=""> (T from); 
 40
 41这里只是举了一个简单的例子,对于更复杂的情况,范型和匿名委托允许你用更富想象力的方法去实现(例如,匿名委托允许你引用栈上的变量)。 
 42
 43下面是  BCL  中的用于  Functional Programming  的范型委托(位于  System  命名空间中): 
 44
 45原型 
 46
 47| 
 48
 49描述   
 50  
 51---|---  
 52  
 53delegate bool Predicate<t> (T obj); 
 54
 55| 
 56
 57访问集合时,对指定元素的断言(  true  或  false  )   
 58  
 59delegate void Action<t> (T obj); 
 60
 61| 
 62
 63访问集合时,对指定元素做出特定动作   
 64  
 65delegate int Comparison<t> (T x, T y); 
 66
 67| 
 68
 69比较两个元素   
 70  
 71delegate U Converter<t, u=""> (T from); 
 72
 73| 
 74
 75把一个元素转换为另外一个,用于在两个集合之间拷贝元素   
 76  
 77List<t> 提供了如下支持  Functional Programming  的方法: 
 78
 79原型 
 80
 81| 
 82
 83描述   
 84  
 85---|---  
 86  
 87int FindIndex(Predicate<t> match); 
 88
 89int FindIndex(int index, Predicate<t> match); 
 90
 91int FindIndex(int index, int count, Predicate<t> match); 
 92
 93| 
 94
 95找出第一个满足断言条件的元素的索引   
 96  
 97int FindLastIndex(Predicate<t> match); 
 98
 99int FindLastIndex(int index, Predicate<t> match); 
100
101int FindLastIndex(int index, int count, Predicate<t> match); 
102
103| 
104
105找出最后一个满足断言条件的元素的索引   
106  
107List<t> FindAll(Predicate<t> match); 
108
109| 
110
111找出所有满足断言条件的元素   
112  
113Nullable<t> Find(Predicate<t> match); 
114
115| 
116
117找出第一个满足断言条件的元素   
118  
119Nullable<t> FindLast(Predicate<t> match); 
120
121| 
122
123找出最后一个满足断言条件的元素   
124  
125bool Exists(Predicate<t> match); 
126
127| 
128
129判断满足断言条件的元素是否存在   
130  
131bool TrueForAll(Predicate<t> match); 
132
133| 
134
135判断是否所有的元素都满足断言条件   
136  
137int RemoveAll(Predicate<t> match); 
138
139| 
140
141删除所有满足断言条件的元素,返回删除的元素数   
142  
143void ForEach(Action<t> action); 
144
145| 
146
147类似  foreach  语句   
148  
149void Sort(Comparison<t> comparison); 
150
151| 
152
153排序   
154  
155List<u> ConvertAll(Converter<t, u=""> converter); 
156
157| 
158
159转换集合元素   
160  
161Array  类提供了类似的支持  Functional Programming  的方法,不同之处在于它们都是类方法而非实例方法,在此限于篇幅不再列举。下面我们来看看前面那个例子换成数组的话是什么样子: 
162
163Contact[] contacts = ...; 
164
165string[] names = Array.ConvertAll<contact, string=""> (contacts, 
166
167delegate(Contact c) { return c.Name; } );</contact,></t,></u></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t></t,></t></t></t></t,></t,></t,></u></u></string></string></contact></string></string></contact></contact></t>
Published At
Categories with Web编程
Tagged with
comments powered by Disqus