首页 > 代码库 > .NET中那些所谓的新语法之三:系统预定义委托与Lambda表达式

.NET中那些所谓的新语法之三:系统预定义委托与Lambda表达式

篇:在上一篇中,我们了解了匿名类、匿名方法与扩展方法等所谓的新语法,这一篇我们继续征程,看看系统预定义委托(Action/Func/Predicate)和超爱的Lambda表达式。为了方便码农们,.Net基类库针对实际开发中最常用的情形提供了几个预定义好的委托,这些委托可以直接使用,无需再重头定义一个自己的委托类型。预定义委托在.Net基类库中使用的比较广泛,比如在Lambda表达式和并行计算中都大量地使用,需要我们予以关注起来!

 
/* 新语法索引 */
 
1.自动属性 Auto-Implemented Properties
2.隐式类型 var
3.参数默认值 和 命名参数
4.对象初始化器 与 集合初始化器 { }
5.匿名类 & 匿名方法
6.扩展方法
7.系统内置委托 Func / Action
8.Lambda表达式
9.标准查询运算符 Standard Query Operator
10.LINQ查询表达式
  自.NET Framework 3.5以来,各种泛型委托纷涌而至,原先需要我们程序员手动定义的一些委托现在我们可以直接使用预定义的委托了,大大提高了开发效率,现在我们就首先来看看这些预定义的泛型委托。
 
一、无返回类型的内置委托—Action
 
1.1 初识Action
MSDN给出的定义:封装一个方法,该方法不具有参数并且不返回值。
  可以使用此委托以参数形式传递方法,而不用显式声明自定义的委托。封装的方法必须与此委托定义的方法签名相对应。也就是说,封装的方法不得具有参数,并且不得返回值。(在 C# 中,该方法必须返回 void)通常,这种方法用于执行某个操作。
 
  现在,我们来看看如何使用Action委托:
 
  (1)先看看之前我们是怎么来使用无返回值委托的例子:
 
 
复制代码
public delegate void ShowValue();
 
public class Name
{
   private string instanceName;
 
   public Name(string name)
   {
      this.instanceName = name;
   }
 
   public void DisplayToConsole()
   {
      Console.WriteLine(this.instanceName);
   }
 
   public void DisplayToWindow()
   {
      MessageBox.Show(this.instanceName);
   }
}
 
public class testTestDelegate
{
   public static void Main()
   {
      Name testName = new Name("Koani");
      ShowValue showMethod = testName.DisplayToWindow;
      showMethod();
   }
}
复制代码
  可以清楚地看出,我们之前要先显式声明了一个名为 ShowValue 的委托,并将对 Name.DisplayToWindow 实例方法的引用分配给其委托实例。
 
  (2)再看看有了Action委托之后我们怎么来达到上面的效果的例子:
 
 
复制代码
public class Name
{
   private string instanceName;
 
   public Name(string name)
   {
      this.instanceName = name;
   }
 
   public void DisplayToConsole()
   {
      Console.WriteLine(this.instanceName);
   }
 
   public void DisplayToWindow()
   {
      MessageBox.Show(this.instanceName);
   }
}
 
public class testTestDelegate
{
   public static void Main()
   {
      Name testName = new Name("Koani");
      Action showMethod = testName.DisplayToWindow;
      showMethod();
   }
}
复制代码
  可以清楚地看出,现在使用 Action 委托时,不必显式定义一个封装无参数过程的委托。
 
1.2 深入Action
  在实际开发中,我们经常将一个委托实例作为一个方法的参数进行传递,于是我们来看一下这个典型的场景,再通过Reflector反编译工具查看编译器到底帮我们做了什么好玩的事儿!
 
  (1)首先来看一下在List集合类型的ForEach方法的定义:
 
复制代码
        //
        // 摘要:
        //     对 System.Collections.Generic.List<T> 的每个元素执行指定操作。
        //
        // 参数:
        //   action:
        //     要对 System.Collections.Generic.List<T> 的每个元素执行的 System.Action<T> 委托。
        //
        // 异常:
        //   System.ArgumentNullException:
        //     action 为 null。
        public void ForEach(Action<T> action);
复制代码
  可以看出,ForEach方法的参数是一个Action委托实例,也就是说是一个无返回值的委托实例。
 
  (2)定义一个实体类,并通过Action委托使用ForEach方法:
 
 
复制代码
    public class Person
    {
        public int ID { get; set; }
 
        public string Name { get; set; }
 
        public int Age { get; set; }
    }
 
    static void ActionDelegateDemo()
    {
         List<Person> personList = GetPersonList();
 
         personList.ForEach(new Action<Person>(delegate(Person p)
         {
                Console.WriteLine(p.ID + "-" + p.Name + "-" + p.Age);
          }));
     }
复制代码
  可以看出,我们为ForEach方法传递了一个Action委托的实例,本质上是一个无返回值的方法指针,遍历输出了每个Person对象的信息。

.NET中那些所谓的新语法之三:系统预定义委托与Lambda表达式