博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
匿名方法,Lambda表达式,高阶函数
阅读量:7212 次
发布时间:2019-06-29

本文共 3624 字,大约阅读时间需要 12 分钟。

原文:

  • 匿名方法

c#2.0引入匿名方法,不必创建单独的方法,因此减少了所需的编码系统开销。 常用于将委托和匿名方法关联,例如

1. 使用委托和方法关联:

this.btnRefresh.Click += 
new
 System.EventHandler(this.btnRefresh_Click);
private
 
void
 btnRefresh_Click(
object
 sender, EventArgs e)
{
    BindData();
}

2. 使用委托和匿名方法关联:

this.btnRefresh.Click +=  delegate(object sender, EventArgs e) { BindData(); };
毫无疑问,如果关联的方法是“一句话方法”的话,代码2更为简洁(实际上编译器在背后为我们创建了类似btnRefresh_Click的方法)。

  • 匿名方法省略参数列表

定义匿名方法时候,参数列表是可以省略的,编译器可以根据委托的签名来确定函数的签名。例如,

delegate void Func(int x);
//带参数
Func f1= delegate (int p) { Console.Write(p); }
// 不带参数
Func f2 = delegate { Console.Write("he");} //编译器自动推断函数签名带int参数
使用不带参数的匿名方法,注意问题
   一是因为没有参数,所以在方法内就不能使用参数。
    二是有些情况不能使用匿名方法,有ambiguous的问题,例如
public Thread(ParameterizedThreadStart start);
public Thread(ThreadStart start);
而// public delegate void ParameterizedThreadStart(object obj);
   // public delegate void ThreadStart();
所以使用
Thread thread = new Thread(
                delegate { sh.LockMyself(); }
            );
就会有问题
Error  The call is ambiguous between the following methods or properties: 'System.Threading.Thread.Thread(System.Threading.ThreadStart)' and 'System.Threading.Thread.Thread(System.Threading.ParameterizedThreadStart)' 
编译器不知道应该将delegate { }这一匿名方法还原为哪个函数,解决方法是显式给定参数列表,让编译器知道你要用那个函数:
Thread thread = new Thread(
                delegate() { sh.LockMyself(); }
            );
Lambda表达式:
Thread thread = new Thread(
           () => 
           {
                sh.LockMyself();
            }
           );

  • Lambda表达式

Lambda表达式为编写匿名方法提供了更简明的函数式的句法,但结果却在编写LINQ查询表达式时变得极其有用,因为它们提供了一个非常紧凑的而且类安全的方式来编写可以当作参数来传递,在以后作运算的函数。

Lambda 表达式和 匿名方法 其实是一件事情。唯一的不同是:他们语法表现形式不同。Lambda 表达式是在语法方面的更进一步的进化。在本质上,他们是一件事情。他们的作用都是:产生方法。即:内联方法。
books是System.Collections.Generic.List类型, 即List<Book>, 有Find方法
使用匿名方法:              books.Find(delegate(Book book){return book.Price < 50;});
使用Lambda表达式:      books.Find(book=>book.Price<50);
book是输入参数; =>读作Go to,是Lambda操作符;book.Price<50是表达式或者语句块。
Lambda表达式中的输入参数省略参数类型,因为当前Find扩展方法对象是books,编译器会自动推断book参数属于BooK类型.
对比另一个例子:

//
 使用匿名方法
string
[] list 
=
 
new
 
string
[] { 
"
abc
"
"
12
"
"
java
"
 }; 
string
[] alist 
=
 Array.FindAll(list, 
                      
delegate
(
string
 s) 
                      { 
                         
return
 s.IndexOf(
"
a
"
>=
 
0
                      } 
                 ); 
foreach
 (
string
 var 
in
 alist) 
Console.WriteLine(var); 
//
 使用Lambda表达式
string
[] list 
=
 
new
 
string
[] { 
"
abc
"
"
12
"
"
java
"
 }; 
string
[] alist 
=
 Array.FindAll(list, s 
=>
 (s.IndexOf(
"
a
"
>=
 
0
)); 

 

Lambda表达式式范例:

//
x的类型省略了,编译器可以根据上下文推断出来,后面跟着的是表达式
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
;}

 

高阶函数(higher-order function)

是指把另一个函数作为参数或返回值的函数。

例如在System.Array类中就有许多静态的高阶函数,其中的ConvertAll方法可谓是最常用的高阶函数之一了: 

private
 
static
 DateTime StringToDateTime(
string
 s) {
 
return
 DateTime.ParseExact(s, 
"
yyyy-MM-dd
"
null
);
}
static
 
void
 Main(
string
[] args) {
 
string
[] dateStrings 
=
 
new
 
string
[] {
 
"
2009-01-01
"
"
2009-01-02
"
"
2009-01-03
"
,
 
"
2009-01-04
"
"
2009-01-05
"
"
2009-01-06
"
,
 };
 
//
 ConvertAll将一个数组映射为另一个数组, new Converter是构建一个委托对象
 
//
 类似于 new System.EventHandler(this.btnRefresh_Click);
 DateTime[] dates 
=
 Array.ConvertAll
<
string
, DateTime
>
(
 dateStrings, 
new
 Converter
<
string
, DateTime
>
(StringToDateTime));
}
//
 C# 2.0中,又引入了匿名方法这一构建委托对象的方式:
DateTime[] dates 
=
 Array.ConvertAll
<
string
, DateTime
>
(
 dateStrings,
 
delegate
(
string
 s) {
 
return
 DateTime.ParseExact(s, 
"
yyyy-MM-dd
"
null
);
 });
//
 新增了Lambda表达式和扩展方法等语言特性,再加上范型类型的自动判断,在C# 3.0中使用匿名方法更是异常简洁,甚至与ruby的语法如出一辙
IEnumerable
<
DateTime
>
 dates 
=
 dateStrings.Select(
 s 
=>
 DateTime.ParseExact(s, 
"
yyyy-MM-dd
"
null
));

 

Reference

 

转载地址:http://delum.baihongyu.com/

你可能感兴趣的文章
HTML(二)选择器
查看>>
C++ 类模板的使用
查看>>
AJAX编程-封装ajax工具函数
查看>>
Common Lisp学习笔记(九)
查看>>
一只菜鸡的话
查看>>
变量声明和定义的区别
查看>>
python之路之课后作业
查看>>
p4475 巧克力王国
查看>>
js中的Attribute
查看>>
Mysql的一些常用命令
查看>>
蓝桥杯:基础练习 闰年判断
查看>>
LeetCode-82-Remove Duplicates from Sorted List II
查看>>
ASP.NET XML读取、增加、修改和删除操作
查看>>
struts2将servlet对象注入到Action中
查看>>
快速排序
查看>>
const变量存储位置及const指针
查看>>
MFC 加载链接库(DLL)错误
查看>>
线性代数的视角理解LSR(least square regression)的参数评估算法本质
查看>>
HDU-2897 邂逅明下
查看>>
牛客暑假多校第二场 F trade
查看>>