从Delegate,匿名方法到Lamdba表达式

来源:互联网 发布:得失寸心知什么意思 编辑:程序博客网 时间:2024/04/30 18:29

 首先看下面的数据集合:


  class Employee
    {
        
public string id { setget; }

        
public string name { setget; }
    }

List
<Employee> lists = new List<Employee>() 
            {
                
new Employee(){ id="1001", name="Ivan"},
                
new Employee(){ id="1002", name="IT"},
                
new Employee(){ id="1003", name="ISD"},
                
new Employee(){ id="1004", name="SE"},
                
new Employee(){ id="1005", name="CI"},
            };

     如果想要从中找到id=1003的记录,我们可以利用泛型集合List的Find方法。由于此方法参数为一个Predicate代理,所以就产生了下面的代码:


 //委托
            Predicate<Employee> pre = new Predicate<Employee>(isMary);
            Employee emp 
= lists.Find(pre);

            Console.WriteLine(emp.id 
+ "---" + emp.name);

  
private static bool isMary(Employee emp)
        {
            
return emp.id == "1003";
        }

     想来这样也是可以达到目的的,但起始还可以简化代码:运用c# 2.0 的特性:匿名方法:


   //匿名方法
            Employee e = lists.Find(delegate(Employee info) { return info.id == "1003"; });

            Console.WriteLine(e.id 
+ "----" + e.name);

     用匿名方法简化了代码,替代了委托的定义。
    而在C#3.X中,我们还可以利用Lamdba表达式进一步优化代码,而其更简洁:


 Employee e2 = lists.Find(info => info.id == "1003");
            Console.WriteLine(e2.id 
+ "---" + e2.name);


注意:lamdba表达式: 参数列表(显示或者隐式)+“=》”+表达式

     上面的演变过程,我们通过反编译可以看到不管是匿名方法,还是lamdba表达式,编译器实际上为我们做了“生成相关代理”的动作,或者说其实际的执行还是通过代理实现的。而整个演变只不过是为开发者开发方便而进行的“前台”“改进”。   
     下面通过lamdba表达式在LINQ中的应用来说明这一点:


 static void Main()
        {
            
string[] arrs = new string[] { "M001","K001","M002","L021","M001","M003"};

            
//采用代理做法
            Func<stringbool> pre = new Func<stringbool>(getStr);
            var result 
= from item in arrs.Where(pre)
                         select item;

            
//采用匿名方法
            var result2 = from item in arrs.Where(delegate(string s) { return s.StartsWith("M"); })
                         select item;


            
//采用lamdba表达式
            var result3 = from item in arrs.Where(s=>s.StartsWith("M"))
                         select item;


            
foreach (string s in result)
            {
                Console.WriteLine(s);
            }

        }

        
private static bool getStr(string s)
        {
            
return s.StartsWith("M");
        }

     IL:


==================代理方式======================
    
L_0034: ldftn bool LINQDemo.LamdbaDemo::isMary(class LINQDemo.Employee)
    
L_003a: newobj instance void [mscorlib]System.Predicate`1<class LINQDemo.Employee>::.ctor(objectnative int)
    
L_003f: stloc.1 
    
L_0040: ldloc.0 
    
L_0041: ldloc.1 
    
L_0042: callvirt instance !0 [mscorlib]System.Collections.Generic.List`1<class LINQDemo.Employee>::Find(class [mscorlib]System.Predicate`1<!0>)
    
L_0047: stloc.2 
    
L_0048: ldloc.2 
    
L_0049: callvirt instance string LINQDemo.Employee::get_id()
    
L_004e: call void [mscorlib]System.Console::WriteLine(string)
    
L_0053: nop 
    
L_0054: ret 
    
======================匿名方法==========================
    
    
L_0030: ldsfld class [mscorlib]System.Predicate`1<class LINQDemo.Employee> LINQDemo.LamdbaDemo::CS$<>9__CachedAnonymousMethodDelegate3
    
L_0035: brtrue.s L_004a
    
L_0037: ldnull 
    
L_0038: ldftn bool LINQDemo.LamdbaDemo::<Main>b__2(class LINQDemo.Employee)
    
L_003e: newobj instance void [mscorlib]System.Predicate`1<class LINQDemo.Employee>::.ctor(objectnative int)
    
L_0043: stsfld class [mscorlib]System.Predicate`1<class LINQDemo.Employee> LINQDemo.LamdbaDemo::CS$<>9__CachedAnonymousMethodDelegate3
    
L_0048: br.s L_004a
    
L_004a: ldsfld class [mscorlib]System.Predicate`1<class LINQDemo.Employee> LINQDemo.LamdbaDemo::CS$<>9__CachedAnonymousMethodDelegate3
    
L_004f: callvirt instance !0 [mscorlib]System.Collections.Generic.List`1<class LINQDemo.Employee>::Find(class [mscorlib]System.Predicate`1<!0>)
    
L_0054: stloc.1 
    
L_0055: ldloc.1 
    
L_0056: callvirt instance string LINQDemo.Employee::get_id()
    
L_005b: call void [mscorlib]System.Console::WriteLine(string)
    
L_0060: nop 
    
L_0061: ret 
=====================lamdba表达式==========================

    
L_0030: ldsfld class [mscorlib]System.Predicate`1<class LINQDemo.Employee> LINQDemo.LamdbaDemo::CS$<>9__CachedAnonymousMethodDelegate3
    
L_0035: brtrue.s L_004a
    
L_0037: ldnull 
    
L_0038: ldftn bool LINQDemo.LamdbaDemo::<Main>b__2(class LINQDemo.Employee)
    
L_003e: newobj instance void [mscorlib]System.Predicate`1<class LINQDemo.Employee>::.ctor(objectnative int)
    
L_0043: stsfld class [mscorlib]System.Predicate`1<class LINQDemo.Employee> LINQDemo.LamdbaDemo::CS$<>9__CachedAnonymousMethodDelegate3
    
L_0048: br.s L_004a
    
L_004a: ldsfld class [mscorlib]System.Predicate`1<class LINQDemo.Employee> LINQDemo.LamdbaDemo::CS$<>9__CachedAnonymousMethodDelegate3
    
L_004f: callvirt instance !0 [mscorlib]System.Collections.Generic.List`1<class LINQDemo.Employee>::Find(class [mscorlib]System.Predicate`1<!0>)
    
L_0054: stloc.1 
    
L_0055: ldloc.1 
    
L_0056: callvirt instance string LINQDemo.Employee::get_id()
    
L_005b: call void [mscorlib]System.Console::WriteLine(string)
    
L_0060: nop 
    
L_0061: ret 

========================生成的匿名方法===========

.method private hidebysig static bool <Main>b__2(class LINQDemo.Employee info) cil managed
{
    
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor()
    
.maxstack 2
    
.locals init (
        [
0bool CS$1$0000)
    
L_0000: ldarg.0 
    
L_0001: callvirt instance string LINQDemo.Employee::get_id()
    
L_0006: ldstr "1001"
    
L_000b: call bool [mscorlib]System.String::op_Equality(stringstring)
    
L_0010: stloc.0 
    
L_0011: br.s L_0013
    
L_0013: ldloc.0 
    
L_0014: ret 
}


==========

    
      lamdba表达式代表一个内嵌的方法,(指向一个匿名的方法),可以传入任何接受delgegate型别的东西,大量用于LINQ中应用到任何匿名方法可以应用的场合,编译器会把lamdba表达式翻译成使用代理的匿名方法。

原创粉丝点击