高阶函数(higher-order function)是指把另一个函数作为参数或返回值的函数。例如 在JavaScript语言中,Function是顶级类型。一个函数就是类型为 Function的顶级对象,自 然就可以作为另一个函数的参数或返回值。例如在Microsoft AJAX Library(ASP.NET AJAX 的客户端类库)中有一个被广泛使用的createDelegate方法。该方法接受一个对象A和一个函 数F作为参数,并返回一个函数R。当调用函 数R时,F函数将被调用,并且保证无论在什么上 下文中,F的this引用都会指向对象A:
Function.createDelegate = function(instance, func) {
return function() {
return callback.apply(a, arguments);
}
}
委托是.NET平台中一种特殊的类型。有人说,它是一种强类型的函数指针。这种说法虽然 细节上略失偏颇,但是从功能和作用上讲不无道理。有了委 托类型,一个方法就能被封装成 一个对象被作为另一个方法的参数或返回值,这自然就为.NET平台上的语言(例如C#, VB.NET)引入了对高阶函数的“ 原生支持”1。例如在System.Array类中就有许 多静态的高阶函数,其中的ConvertAll方法可谓是最常用的高阶函数之一了:
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",
};
DateTime[] dates = Array.ConvertAll<string, DateTime>(
dateStrings, new Converter<string, DateTime> (StringToDateTime));
}
ConvertAll
将一个数组映射为另一个数组,就好像Ruby中array类型的map方法一样,但是如果您会发 现ruby的“内联”写法会方便许多。于是在C# 2.0中,又引入了匿名方法这一构建委托对象 的方式:
string[] dateStrings = new string[] {
"2009-01-01", "2009-01-02", "2009-01-03",
"2009-01-04", "2009-01-05", "2009-01-06",
};
DateTime[] dates = Array.ConvertAll<string, DateTime>(
dateStrings,
delegate(string s) {
return DateTime.ParseExact(s, "yyyy-MM-dd", null);
});
匿名方法并不只是“匿名”的方法,它甚至可以构造一个闭包给开发带来极大的便利。可 见在2.0中已经为高阶函数在C#中的运用打下了坚实的基 础。而且,由于新增了Lambda表达 式和扩展方法等语言特性,再加上范型类型的自动判断,在C# 3.0中使用匿名方法更是异常 简洁,甚至与ruby的语法如出一辙:
IEnumerable<DateTime> dates = dateStrings.Select(
s => DateTime.ParseExact(s, "yyyy-MM-dd", null));