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在时间和空间的效率都要高
-
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表达式中必须用到