匿名方法与Lambda表达式

1.匿名方法

在学习委托时,我们知道委托实例至少要绑定一个方法才能使用,而调用委托实际上是调用了它所关联地方法。一般来说,需要定义一个与委托签名相符的方法,并使之与委托变量关联。如以下代码:

Action deleg=new Action(CallMethod);//声明并实例化委托变量

private static void CallMethod()//与委托关联的方法

{.........}

会发现以上写法并不简洁,因此引入了“匿名方法”,它不需要命名,用一个delegate关键字代表方法的名字,没有访问修饰符,也不需要返回类型。

例如上面的例子可以简写如下:

Action deleg=delegate()

{........};

当委托既有参数又有返回值的时候,匿名方法中就也要相应定义参数,如果委托的签名中有返回值,则在匿名方法中就直接使用return返回即可,如下实例:

Func<int,int,int> f=delegate(int x,int y)

{ return x+y;};

int result=f(1+2);//调用委托

其实上例所用的委托的原型如下:delegate TResult Func<in T1,in T2,out TResult>(T1 x,T2 y);

如果委托要关联地方法在代码中没有重复使用,使用匿名方法会非常方便,当方法在代码中多个地方都用到,就不应该在使用匿名方法。

 

2.Lambda表达式

Lambda表达式其实就是更为简洁的匿名方法表示法,以“=>”作为分隔符,其左边为匿名方法的参数列表,右边为匿名方法的语句,即:(参数列表)=><语句>

对于没有参数的委托,Lambda表达式如下:()=><语句>

     2.1 Lambda表达式用于给委托变量赋值

     (1)对于没有参数,返回值为void类型的委托

      Action a=()=>{/*........*/};

      如果“=>”右边只有一句代码,则可以省略大括号,写出:Action a=()=>Console.WriteLine("");

     (2)对于有参数的委托

     Action<string,int> a=(string name,int age)=>Console.WriteLine("");

     由于Lambda表达式可以根据委托来识别参数类型,所以可以省略(string name,int age)中的参数类型。

     (3)对于有返回值的委托(非void类型),则直接用return 返回即可。

     Func<int,int ,int> a=(a,b)=>{return a*b;};

     如果“=>”后边只有一句代码,可以吧return和大括号省略,如下所示:

     Func<double, string> a=(n)=>n.ToString("C2");

 

     2.2 Lambda表达式用于参数传递

     比如.NET类库的许多扩展方法以及LINQ表达式都可以使用Lambda表达式传递参数。示例代码:

     

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Test
{
    #region 定义类型
    public class Student
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime Date { get; set; }
    }
    #endregion

    class Program
    {
        static void Main(string[] args)
        {
            List<Student> stus = new List<Student>();
            stus.Add(new Student { Name = "小王", Age = 22, Date = new DateTime(2012, 9, 22) });
            stus.Add(new Student { Name = "小刘", Age = 23, Date = new DateTime(2013, 1, 10) });
            stus.Add(new Student { Name = "小红", Age = 21, Date = new DateTime(2012, 3, 2) });
            
            // 将学员的入学日期按升序排序
            var res = stus.OrderBy(stu => stu.Date);
            Console.WriteLine("学员的入学日期按升序排序:");
            foreach (Student s in res)
            {
                Console.WriteLine("姓名:{0},年龄:{1},入学日期:{2:yyyy-M-d}", s.Name, s.Age, s.Date);
            }
            Console.ReadKey();
        }
    }
}

以上代码使用了OrderBy扩展方法的以下重载:

public static IOrderedEnumerble<TSource> OrderBy<TSource,TKey>(this IEnumerble<TSource> source,Func<TSource,TKey> keySelector);

在调用时,主要关注keySelector参数,因为第一个参数是要扩展的类型,由编译器调用。keySelector参数是Func<TSource,TKey>,输入类型为TSource,TKey是要返回的值,OrderBy方法将根据TKey来进行排序。实例中,stu会自动识别为Student类型,“=>”右边直接将stu的Date属性值返回,OrderBy方法通过调用传递给keySelector参数的委托来获取每个Student实例的Date属性值,以便进行排序。

posted @ 2015-10-19 18:17  追求沉默者  阅读(1141)  评论(0编辑  收藏  举报