zoukankan      html  css  js  c++  java
  • Delegate,Annonymous Method,Extension Methods,Lambda Expression

    简介:本文简单介绍委托、匿名方法、扩展方法和 Lambda Expression。 仅供初次接触这些技术的同学参考学习。

     List<int> list = new List<int> { 2, 3, 76, 63, 4, 64, 23 };

     //当你第一次看到下面这条语句时,你可能很难马上理解它的含义

     list.Where( x => x >20 );

     下面我们来一步一步演示它的演化过程。

     1. delegate

       委托是一种类型,它相当于 C++ 中的函数指针,指向一个特定的函数。

       如:public delegate int MyDelegate(int i);

      它定义了一个返回值为 int 且含有一个 int 型参数的委托 MyDelegate,凡是符合这种形式的方法都可以赋给我们的委托。  

      下面我们定义一个方法:

      public static int Fun(int i)  {   return i * 5;  }    

      这个方法符合我们定义的委托的形式:返回值为 int ,一个 int 型参数。  所以可以用来实例化我们的委托。

      MyDelegate del = new MyDelegate(Fun);

       //or

      //MyDelegate del = Fun;

      现在就可以用委托来调用我们的方法了:

      del(6);    

      委托其实是一个类,所以只能在类的外部定义。  那我们为什么多此一举用委托来调用函数呢?

      主要是一个委托可以指向具相同形式的多个函数,这使得委托可以实现很多灵活的应用。

      如实现很多好的设计模式,像观察者模式等,  C# 中的 event 等都是基于委托实现的。 

    2. Annonymous Method(匿名方法)

        匿名方法就是一个没有名字的方法,下面我们赋给我们的委托一个匿名的方法  

        MyDelegate del = delegate(int i)  {   return i * 6;  };  

    3. Lambda Expression

       有了 Lambda Expression 我们就可以这样写了   

       MyDelegate del = i => i * 6;

       是不是更简单了 => 左边的 i 是参数,右边是函数体(返回 i*6)。

       当有多个参数或函数体有多条语句时就可以写成这样了

       MyDelegate del = (x, y) =>     {      x = 3;      y = 5;      return x + y;     };      

    4. Extension Methods   

       扩展方法可以给一个不可变的类添加方法,扩展方法是一个静态方法,不过可以用类的实例进行调用,

      看起来和调用类中的普通方法没什么区别。      

      下面我们扩展 string 类,增加一个 ToInt32Extension 方法

      public static class ExtensionMethods  

      {

        public static int ToInt32Extension(this string s)    

        {    

          return Int32.Parse(s);    

        }  

     }  

      扩展方法必须放在一个静态非泛型的类中,否则编译会出错。

      this 是扩展方法的关键字,后面跟上你要扩展的类。

      当然扩展方法也可以带参数,如  

      public static class ExtensionMethods

      {    

      public static int ToInt32ExtensionAddInteger(this string s,int value)    

       {    

         return Int32.Parse(s) + value;    

       }  

      }  

     下面我们就可以用类的实例就行调用了  

     string str = "45";

     s.ToInt32Extension();  

     也可直接调用静态方法如:

     ToInt32Extension(s);  

     不过不会这样用,这就体现不出扩展的意思了,但运行时应该就是把我们实例的引用传到静态方法中。

     扩展方法在 LINQ 查询中用的最多,看我们扩展自己的 where 查询子句。  

    public static IEnumerable<TSource> MyOwnWhere<TSource>(this IEnumerable<TSource> source,      Func<TSource, bool> predicate)

     {   

      foreach (var item in source)   

      {  

          if (predicate(item))     

          yield return item;  

       }   

     }  

     IEnumerable<TSource>是我们要扩展的类,它是一个泛型类。

     同样它返回一个 IEnumerable<TSource> 集合。

     Func<TSource, bool>是参数,Func是一个泛型委托,它的返回值是 bool 类型。

     yield 的意思是将所有满足条件的 item 构成一个集合返回。

     这样我们就可以把筛选的条件作为函数传进去,当然就可以传匿名方法和  Lambda Expression 了。    

     最后让我们测试一下

     List<int> list = new List<int> { 2, 3, 76, 63, 4, 64, 23 };    

     //我们可以传一个匿名的方法进去  

     //var list2 = list.MyOwnWhere(delegate(int x){return x > 20;});  

     这里你可能要问我们没有扩展 List<T> 类啊? 为什么 List 的实例也能访问到呢?

     这是由于我们已经扩展了 IEnumerable<T> 接口 ,当你扩展一个接口时,

     所有实现这个接口的类的实例也都能访问到扩展方法了。当然 List<T> 是集合类,它实现了 IEnumerable<T> 接口。

     但更一般的是传一个 Lambda Expressions 进去

     你在LINQ查询中经常看到  

     var list2 = list.MyOwnWhere( x => x > 20);    

     foreach (int x in list2)  

    {  

      Console.WriteLine(x);  

    }  

    最后它将返回数组中大于 20 的数字。

    其它的 LINQ 扩展查询方法如 Select、Single、order by 等都是这样实现的。

    现在希望你再看到这种表达式时不要感觉陌生了。

  • 相关阅读:
    【算法】LeetCode算法题-Count And Say
    【算法】LeetCode算法题-Search Insert Position
    使用POI设置excel背景色
    Ubuntu中开启MySQL远程访问功能,并将另一个数据库服务器中的数据迁移到新的服务器中
    利用mybatis_generator自动生成Dao、Model、Mapping相关文件
    Meven笔记
    js调用百度地图API创建地图
    MySQL中日期与字符串相互转换,并进行日期比较查询
    java中将汉字转换成16进制
    Java中将16进制字符串转换成汉字
  • 原文地址:https://www.cnblogs.com/lesliefang/p/2427821.html
Copyright © 2011-2022 走看看