您的位置:首页 > 编程语言 > C#

C#Lambda表达式

2016-02-25 22:05 501 查看

需求

有时候我们需要传递一个很方法的引用,我们很确定这个方法仅仅会调用这一次,单独为它创建一个方法感觉有些浪费,但是又必须用到这个方法。又或者临时需要一个方法,但是思考半天想不出该给这个方法取什么名字(有过这个经历的同学握个爪)。这个时候Lambda就派上用场了。

是什么

Lambda 表达式是一种可用于创建委托或表达式目录树类型的匿名函数。通过使用 lambda 表达式,可以写入可作为参数传递或作为函数调用值返回的本地函数。Lambda 表达式对于编写 LINQ 查询表达式特别有用。

若要创建 Lambda 表达式,需要在 Lambda 运算符 => 左侧指定输入参数(如果有),然后在另一侧输入表达式或语句块。例如,lambda 表达式 x => x * x 指定名为 x 的参数并返回 x 的平方值,你可以将此表达式分配给委托类型。

说明

=> 运算符具有与赋值运算符 (=) 相同的优先级并且是右结合运算(参见“运算符”文章的“结合性”部分)。

Lambda 在基于方法的 LINQ 查询中用作标准查询运算符方法(如 Where)的参数。

使用基于方法的语法在 Enumerable 类中调用 Where 方法时(如在 LINQ to Objects 和

LINQ to XML 中一样),参数是委托类型
System.Func<T, TResult>
。使用 Lambda表达式创建该委托最为方便。例如,当你在 System.Linq.Queryable 类中调用相同的方法时(如在LINQ to SQL中一样),参数类型为 System.Linq.Expressions.Expression,其中 Func是最多具有十六个输入参数的任何一个Func委托。同样,Lambda 表达式只是一种非常简洁的构造该表达式目录树的方式。尽管事实上通过Lambda创建的对象具有不同的类型,但Lambda 使得 Where调用看起来类似。

注意

 如果Lambda表达式要获取参数,就在=>操作符左侧的圆括号内指定。可省略参数类型,C#编译器能根据Lambda表达式的上下文进行推断。如果希望Lambda表达式永久(而不是局部)更改参数值,可以用“传引用”的方式传递参数(使用ref关键字),但不推荐这样做。

 Lambda表达式可以返回值,但返回类型必须与即将添加这个Lambda表达式的委托的类型匹配。

 Lambda表达式的主体可以是简单表达式,也可以是C#代码块(代码块可包含多个语句、方法调用、变量定义等等)。

 Lambda表达式方法中定义的变量会在方法结束时离开作用域。

 Lambda表达式可访问和修改Lambda表达式外部的所有变量,只要那些变量在Lambda表达式定义时,和Lambda表达式处在相同的作用域中。

怎么用

准备工作

委托定义

public delegate void LambdaHandle0();
public delegate void LambdaHandle0s();
public delegate void LambdaHandle1(int x);
public delegate void LambdaHandle2(int x,int y);
public delegate void LambdaHandle3(ref int x,int y);


事件定义

public class LambdaEvent{
//无参事件1
public event LambdaHandle0 thisEvent0;
//无参事件2
public event LambdaHandle0s thisEvent0s;
//一个整形参数事件
public event LambdaHandle1 thisEvent1;
//两个整形参数事件
public event LambdaHandle2 thisEvent2;
//两个整形参数事件,第一个参数为引用传递
public event LambdaHandle3 thisEvent3;

public void callEvent0(){
if(thisEvent0!=null)
thisEvent0 ();
}

public void callEvent0s(){
if(thisEvent0s!=null)
thisEvent0s ();
}

public void callEvent1(int x){
if(thisEvent1!=null)
thisEvent1 (x);
}

public void callEvent2(int x,int y){
if(thisEvent2!=null)
thisEvent2 (x,y);
}
public void callEvent3(ref int x,int y){
if(thisEvent3!=null)
thisEvent3 (ref x,y);
}
}


用于事件的方法定义

private void myFunction(string str){
Debug.Log ("str="+str);
}


具体用法

实例化事件

LambdaEvent myEvent=new LambdaEvent();


###无参表达式

myStr="myStr";
myEvent.thisEvent0+=()=>myFunction(myStr);
myEvent.callEvent0 ();




myEvent.thisEvent0s+=()=>Debug.Log("Lambda");
myEvent.callEvent0s ();




一个参数的表达式

int a=10;
//参数类型省略,自动根据上下文判断
myEvent.thisEvent1 +=x => Debug.Log("x*x="+ x * x);
myEvent.callEvent1 (a);




多个参数的表达式

int a=10,b=10;
myEvent.thisEvent2+=(x,y)=>{x=x*y;Debug.Log("x="+x);};
myEvent.callEvent2 (a,b);
//普通传值,参数值不变
Debug.Log ("a="+a);




传递引用参数的表达式

//第一个参数为引用。注意此时必须指明参数类型
myEvent.thisEvent3+=(ref int x,int y)=>{x=x*y;Debug.Log("x="+x);};
myEvent.callEvent3 (ref a,b);
Debug.Log ("ref a="+a);




带有标准查询运算符的Lambda

//用于泛型委托Func
Func<int, bool> myFunc = x => x == 5;
Debug.Log("myFunc(5)="+myFunc(5));




//用于Linq查询
int[] number = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
Debug.Log ("Count="+number.Count(n=>n%2==1));




List<int> numList = number.TakeWhile (n => n < 6).ToList ();
if (numList != null)
foreach (int i in numList)
Debug.Log (i);




转载请注明出处:http://blog.csdn.net/ylbs110/article/details/50741123

完整脚本

using UnityEngine;
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;

public delegate void LambdaHandle0();
public delegate void LambdaHandle0s();
public delegate void LambdaHandle1(int x);
public delegate void LambdaHandle2(int x,int y);
public delegate void LambdaHandle3(ref int x,int y);

public class MyLambda : MonoBehaviour {
void Start () {
LambdaEvent myEvent=new LambdaEvent();
string myStr="myStr"; myEvent.thisEvent0+=()=>myFunction(myStr); myEvent.callEvent0 ();

myEvent.thisEvent0s+=()=>Debug.Log("Lambda");
myEvent.callEvent0s ();

int a=10,b=10;
//参数类型省略,自动根据上下文判断
myEvent.thisEvent1 +=x => Debug.Log("x*x="+ x * x);
myEvent.callEvent1 (a);

myEvent.thisEvent2+=(x,y)=>{x=x*y;Debug.Log("x="+x);};
myEvent.callEvent2 (a,b);
//普通传值,参数值不变
Debug.Log ("a="+a);

//第一个参数为引用。注意此时必须指明参数类型
myEvent.thisEvent3+=(ref int x,int y)=>{x=x*y;Debug.Log("x="+x);};
myEvent.callEvent3 (ref a,b);
Debug.Log ("ref a="+a);

//用于泛型委托Func Func<int, bool> myFunc = x => x == 5; Debug.Log("myFunc(5)="+myFunc(5));

//用于Linq查询 int[] number = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 }; Debug.Log ("Count="+number.Count(n=>n%2==1));

List<int> numList = number.TakeWhile (n => n < 6).ToList ();
if (numList != null)
foreach (int i in numList)
Debug.Log (i);

}
private void myFunction(string str){
Debug.Log ("str="+str);
}
}

public class LambdaEvent{ //无参事件1 public event LambdaHandle0 thisEvent0; //无参事件2 public event LambdaHandle0s thisEvent0s; //一个整形参数事件 public event LambdaHandle1 thisEvent1; //两个整形参数事件 public event LambdaHandle2 thisEvent2; //两个整形参数事件,第一个参数为引用传递 public event LambdaHandle3 thisEvent3; public void callEvent0(){ if(thisEvent0!=null) thisEvent0 (); } public void callEvent0s(){ if(thisEvent0s!=null) thisEvent0s (); } public void callEvent1(int x){ if(thisEvent1!=null) thisEvent1 (x); } public void callEvent2(int x,int y){ if(thisEvent2!=null) thisEvent2 (x,y); } public void callEvent3(ref int x,int y){ if(thisEvent3!=null) thisEvent3 (ref x,y); } }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: