委托定义类型,类型指定特定方法签名。 可将知足此签名的方法(静态或实例)分配给该类型的变量,而后(使用适当参数)直接调用该方法,或将其做为参数自己传递给另外一方法再进行调用。 如下示例演示了委托的用法。程序员
using System; using System.Linq; public class Program { public delegate string Reverse(string s); static string ReverseString(string s) { return new string(s.Reverse().ToArray()); } static void Main(string[] args) { Reverse rev = ReverseString; Console.WriteLine(rev("a string")); } }
public delegate string Reverse(string s);
行建立特定签名的委托类型,在本例中即接受字符串参数并返回字符串参数的方法。static string ReverseString(string s)
方法与定义的委托类型具备彻底相同的签名,用于实现委托。Reverse rev = ReverseString;
行显示可将方法分配给相应委托类型的变量。Console.WriteLine(rev("a string"));
行演示如何使用委托类型的变量来调用委托。为简化开发过程,.NET 包含一组委托类型,程序员可重用这些类型而无需建立新类型。 其中包括 Func<>
、Action<>
和 Predicate<>
,可用于 .NET API 的各个位置,无需定义新委托类型。 固然,从这三者的签名能够看出它们之间存在某些差别,主要影响其既定用途:api
Action<>
用于须要使用委托参数执行操做的状况。Func<>
一般用于现有转换的状况,也就是说须要将委托参数转换为其余结果时。 最好的示例就是投影。Predicate<>
用于须要肯定参数是否知足委托条件的状况。 也可将其写做 Func<T, bool>
。如今可以使用 Func<>
委托而非自定义类型从新编写上述示例。 程序将照旧继续运行。this
using System; using System.Linq; public class Program { static string ReverseString(string s) { return new string(s.Reverse().ToArray()); } static void Main(string[] args) { Func<string, string> rev = ReverseString; Console.WriteLine(rev("a string")); } }
对于此简单示例而言,在 Main
方法以外定义方法彷佛有些多余。 所以 .NET Framework 2.0 引入了匿名委托的概念。 在其支持下,可建立“内联”委托,而无需指定任何其余类型或方法。 只需在所需位置内联委托的定义便可。spa
例如,要进行切换并使用匿名委托筛选出只有偶数的列表,而后将其打印到控制台。code
using System; using System.Collections.Generic; public class Program { public static void Main(string[] args) { List<int> list = new List<int>(); for (int i = 1; i <= 100; i++) { list.Add(i); } List<int> result = list.FindAll( delegate (int no) { return (no % 2 == 0); } ); foreach (var item in result) { Console.WriteLine(item); } } }
如你所见,该委托的正文只是一组表达式,其余全部委托也是如此。 但它并不是单独定义,而是在调用List<T>.FindAll 方法时临时引入。blog
可是,即便使用此方法,仍有许多能够丢弃的代码。 此时就须要使用 lambda 表达式。事件
lambda 表达式(或简称“lambda”)在 C# 3.0 中做为语言集成查询的 (LINQ) 核心构建基块被首次引入。 这种表达式只是使用委托的更方便的语法。 它们将声明签名和方法正文,但在分配到委托以前没有本身的正式标识。 与委托不一样,可将其做为事件注册的左侧内容或在各类 LINQ 子句和方法中直接分配。开发
因为 lambda 表达式只是指定委托的另外一种方式,所以应可从新编写上述示例,令其使用 lambda 表达式而不是匿名委托。字符串
using System; using System.Collections.Generic; public class Program { public static void Main(string[] args) { List<int> list = new List<int>(); for (int i = 1; i <= 100; i++) { list.Add(i); } List<int> result = list.FindAll(i => i % 2 == 0); foreach (var item in result) { Console.WriteLine(item); } } }
在前面的示例中,所使用的 Lambda 表达式为 i => i % 2 == 0
。 再次强调,它只是使用委托的一种很是方便的语法,所以其实际行为与使用匿名委托时相同。get
再次强调,lambda 只是委托,这意味着可将其顺利用做事件处理程序,如如下代码片断所示。
public MainWindow() { InitializeComponent(); Loaded += (o, e) => { this.Title = "Loaded"; }; }
此上下文中的 +=
运算符用于订阅事件。