lambda表达式

转载至:https://www.cnblogs.com/sntetwt/p/5402734.html  

 

  C#匿名委托,匿名方法,匿名对象,lambda表达式

一、匿名类型

可通过使用new 运算符和对象初始值创建匿名对象

var v= new{ Name="MIKE" , message="hello"};

var v = new[] { 
    new { Name = "Micro", Message = "Hello" }, 
    new { Name = "Soft", Message = "Wold!" }
};

匿名类型通常用在查询表达式的 select 子句中,以便返回源序列中每个对象的属性子集。
var Query = from p in v select new { p.Name };
foreach (var o in Query)
{
    Console.WriteLine(o.Name);
}
可以查找对象
IEnumerable<v> results = people.Where(delegate(v p) { return p.Name == "Micro"; }); 

二、匿名方法
要将代码块传递为委托参数 例如:
点击事件
button1.Click += delegate(System.Object o, System.EventArgs e)

    System.Console.WriteLine("Hello");
};
this.Loaded += delegate
{
    InitializeEvent();
};

加载事件
this.Loaded += (sl, el) =>
{
    System.Console.WriteLine("Hello");
    this.button1.Click += (sender, e) =>
    {
        System.Console.WriteLine("Wold!");
    }
}

匿名方法与线程
System.Threading.Thread thread = new System.Threading.Thread(delegate(j)
{
    System.Console.WriteLine("Hello");
});
thread.Start();

System.Threading.ThreadPool.QueueUserWorkItem((s) =>
{
    Action f = () =>
    {
        System.Console.WriteLine("Wold!");
    };
}

使委托与匿名方法关联
delegate void DEL(string s);
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    DEL p = delegate(string j)
    {
        System.Console.WriteLine(j);
    };
    p("Hello");
}

三、Func,Func是有返回值的泛型委托
Func<int> 表示无参,返回值为int的委托
Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型)返回值为int的委托
Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void

匿名方法只能在使用委托的时候创建,事实上,它们通过delegate关键字创建。
使用示例:
var func = new Func<bool, int>(delegate(bool x) { return x ? 10 : 5; });
int ret = func(true);

四、匿名事件
btn.Click += delegate(object o, EventArgs e) {  };

五、Lambda 表达式,Func<T>委托
MSDN中写道:“Lambda 表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式树类型。
所有Lambda表达式都使用Lambda运算符=>
左边是输入参数列表
1.一个参数:param=>expr
2.多个参数:(param-list)=>expr

右边是表达式或语句块
(参数列表)=>表达式或语句块 

合法的Lambda表达式
1、(x, y) => x * y                    //多参数,隐式类型=> 表达式  
2、x => x * 5                        //单参数, 隐式类型=>表达式  
3、x => { return x * 5; }            //单参数,隐式类型=>语句块  
4、(int x) => x * 5                    //单参数,显式类型=>表达式  
5、(int x) => { return x * 5; }     //单参数,显式类型=>语句块  
6、() => Console.WriteLine()        //无参数 

在编写Lambda表达式时,可以忽略参数的类型,因为编译器能够根据上下文直接推断参数的类型,示例代码如下。
(x, y) => x + y                        //多参数,隐式类型=> 表达式 

    • x => x+1  
      deleage(int x){return x+1;}
    • //后面跟着的是语句块  
      x=>{return x+1;}
    • delegate(int x){return x+1;}  //输入参数也可以带类型,带类型后别忘记小括号哦
    • (int x) => x+1  
      delegate(int x){return x+1;}
    • //也可以多个输入参数,逗号分隔,别忘记小括号  (x,y) => x+y
    • delegate(int x,int y){return x+y;}  //无参的也行
    • () => 1
    • delegate(){return 1;}

[C#]list的removeall用法

如有两个list,list<byte> a 和 list<byte> b, 如果想要去掉a和b同时有的元素的时候可以用removeall

list.RemoveAll(Predicate<T> match);

只需要一行代码,其中Predicate为对方法的委托,他会根据传递的对象和委托中的定义是否匹配来返回true和false。

a.RemoveAll(data=>b.Contains(data));

data为自己定义的list a中的元素,类似foreach(data in list)

 

delegate、Lambda表达式、Func委托和Expression(TDelegate)表达式目录树

一、delegate

MSDN:一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似。与 C 中的函数指针不同,委托是面向对象的、类型安全的和保险的。委托的类型由委托的名称定义

    class Program
    {
       const int num = 100;
       delegate bool delCompare(int a); //定义委托数据类型delCompare(传入int参数,返回bool类型的方法)
       static void Main(string[] args)
        {
            delCompare hander = DelegateMethod; //定义委托变量hander,给hander赋函数DelegateMethod
            hander(1); //运行委托hander,间接的调用运行DelegateMethod方法
        }
 
       public static bool DelegateMethod(int a)
       {
           return a > num;
       }
    }

 

其他方法:委托指向方法

delCompare hander=new delCompare(DelegateMethod);

Console.Write(hander(1));

 

用IL Disassemble查看

 

 

二、匿名委托

匿名委托即使用了匿名方法的委托,IL层中的代码中会为匿名函数生一个静态的函数,本次的代码中的函数名是:CS$<>9__CachedAnonymousMethodDelegate1

    class Program
    {
        const int num = 100;
        delegate bool delCompare(int a);
       static void Main(string[] args)
        {
            delCompare del = delegate(int a) { return a > num; };
        }
    }

 


用IL Disassemble查看 

 

 

三、Lambda表达式

        使用Lambda表达式与上一个Demo中使用匿名函数生成的IL代码是完全一样的

       

    class Program
    {
        const int num = 100;
        delegate bool delCompare(int a);//第1步:定义委托
       static void Main(string[] args)
        {
            delCompare del = a => a > num;//第2步:委托指向方法
        }
    }

 

       执行Lambda 表达式:

             del(1)

 

 

四、Func<T1..TResult> :封装方法

使用Func<T1…TResult>中的Demo中,在IL层代中有所不同。代码中没有用到delegate,相当于在Main方法中直接调用了一个静态方法。理论上Func<T1…TResult>比delegate在时间和空间的效率都要高

  1.     class Program
        {
            const int num = 100;
            //delegate bool delCompare(int a);
           static void Main(string[] args)
            {
                Func<int, bool> del = a => a > num;
            }
        }

    封装方法:Func<int,bool> del = a=>a>num

执行方法:del(1)

 

 

 

五、Expression(TDelegate) :将强类型Lamda表达式表示为数据结构

表达式目录树以数据形式表示语言级别代码。数据存储在树形结构中。表达式目录树中的每个节点都表示一个表达式。以下Demo中IL层的代码中并未生成任何静态函数。

    class Program
    {
        const int num = 100;
        //delegate bool delCompare(int a);
       static void Main(string[] args)
        {
            Expression<Func<int, bool>> exp = a => a > num; //生在表达式
            Func<int,bool> fun = exp.Compile(); //编辑表达式
            fun(1); //执行表达式
        }
    }

 

Expression<Func<int,bool>> exp =a=>a>num

 

查看Main函数,在IL层代码中会对Expression动太编译生成实例!0,再通过Invoke(!0)调用方法

 

IL_0045: callvirt instance !0 class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<int32,bool>>::Compile()
IL_004a: stloc.1 
IL_004b: ldloc.1 
IL_004c: ldc.i4.1 
IL_004d: callvirt instance !1 class [mscorlib]System.Func`2<int32,bool>::Invoke(!0)
IL_0052: pop 
IL_0053: ret 

总结:

匿名delegate和Lambda表达式本质是一样的,Func<T1..TResult>委托与delegate不同,它没有委托的异常调用等特性,在IL层生成的代码不同,执行方式不同。Expression(TDelegate)则是语言级别的,用于动太生成表达式,理论上Expression(TDelegate)效率最差。但在Linq表达式中必须用到

 

posted @ 2018-07-30 17:22  wonderfulviews  阅读(136)  评论(0编辑  收藏  举报