自C#3.0开始,就可以使用一种新语法把实现代码赋予委托:Lambda表达式。只要有委托参数类型的地方,就可以使用Lambda表达式。
Lambda表达式的语法比匿名方法简单。如果所调用的方法有参数,且不需要参数,匿名方法的语法就比较简单,因为这样不需要提供参数。
直接上一些例子,读者可以自行运行调试。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
static
void
Main(
string
[] args)
{
//1、lambda之hello world.
Func<
string
,
string
> lambda = param =>
{
return
param;
};
Console.WriteLine(lambda(
"hello lambda."
));
//2、lambda之参数
Func<
double
,
double
,
double
,
double
> cube = (
double
x,
double
y,
double
z) => x * y * z;
Console.WriteLine(cube(1, 2, 3));
//输出6
//更进一步,参数的类型可以省略
Func<
double
,
double
,
double
,
double
> cude1 = (x, y, z) => x * y * z;
Console.WriteLine(cude1(2, 4, 6));
//输出48
//3、lambda之调用外部参数
int
someValue = 4;
Func<
double
,
double
,
double
,
double
> f = (x, y, z) => x + y + z + someValue;
Console.WriteLine(f(1, 2, 3));
//1+2+3+4=10
}
|
在winform编程中,我们经常给某个按钮添加Click事件,最原始的写法是直接双击按钮,生成Click事件的代码,我们就可以直接在里面写方法了。其实这是vs替我们做了很多工作,其中就有在designer.cs文件中,生成了 this.button1.Click += new System.EventHandler(this.button1_Click);这样的代码,事件要注册才能触发。
我们采用匿名委托的写法,在窗体的Form_Load事件中添加如下代码,则可以触发button1的Click事件。
1
2
3
4
|
this
.button1.Click +=
delegate
(
object
ss, EventArgs ee)
{
MessageBox.Show(
"hello,this is button1.Click event..."
);
};
|
再看看Lambda表达式的用法。
1
2
3
4
|
this
.button1.Click += (ss, ee) =>
{
MessageBox.Show(
"hello,this is button1.Click event..."
);
};
|
是不是更加简洁?
我们再看一下,从匿名方法到Lambda简写的演化过程,借一张图。
从这个演化过程,可以看出C#语言的发展变化过程。
下面详细演示一下Lambda的应用实例。
首先第一个实例我们应用Lambda对一个List<Student>列表进行循环、查找、排序等操作。
首先我们提供一个实体类:
1
2
3
4
5
6
7
8
9
10
11
|
public
class
Student
{
public
Student(
string
name,
int
age)
{
this
.Name = name;
this
.Age = age;
}
public
string
Name {
get
;
set
; }
public
int
Age {
get
;
set
; }
}
|
然后我们初始化一个List,
1
2
3
4
5
6
7
|
//初始化3个Student对象
var
students =
new
List<Student>()
{
new
Student(
"zhang3"
,18),
new
Student(
"li4"
,22),
new
Student(
"wang5"
,20)
};
|
1
2
|
//定义1个打印函数
Action<Student> print = student => Console.WriteLine(
string
.Concat(student.Name,
":"
, student.Age));
|
那么,我们就可以先循环输出一下:
1
|
students.ForEach(print);
//循环打印输出
|
如果我们要找到年龄大于20岁的学生,可以这样:
1
|
students.FindAll(student => student.Age > 20).ForEach(print);
|
进一步,我们按照学生的年龄进行排序:
1
2
|
students.Sort((f1, f2) => f1.Age.CompareTo(f2.Age));
students.ForEach(print);
//年龄从小到大排序后输出
|
现在,我们按照在students列表里再加一个学生:
1
2
3
4
5
6
7
|
var
students =
new
List<Student>()
{
new
Student(
"zhang3"
,18),
new
Student(
"li4"
,22),
new
Student(
"wang5"
,20),
new
Student(
"zhao6"
,20)
};
|
现在要按照年龄进行分组,并统计出各个年龄阶段的人数:
1
2
|
var
result = students.GroupBy(x => x.Age).Select(x =>
string
.Concat(x.Key,
":"
, x.Count()));
//先进行分组,再进行投影
result.ToList().ForEach(x => Console.WriteLine(x.ToString()));
//循环输出得到结果
|
再提供一个综合性的例子,这是论坛里的caozhy版主提供的一个例子。用Lambda表达式实现快速排序。
1
2
3
4
5
6
7
8
9
10
11
|
Func<Func<
int
,
int
,
bool
>, Func<
int
[],
int
[]>> filter = x =>
new
Func<
int
[],
int
[]>(y => y.Skip(1).Where(z => x(y[0], z)).ToArray());
Func<
int
[],
int
[]> qsort = x => x;
Func<
int
[],
int
[]> lesser = dt => filter((x, y) => y < x)(dt);
Func<
int
[],
int
[]> greater = dt => filter((x, y) => y >= x)(dt);
qsort = dt => dt.Length > 1
? qsort(lesser(dt)).Concat(
new
int
[] { dt[0] }).Concat(qsort(greater(dt))).ToArray() : dt;
int
[] data = { 4, 3, 1, 4, 6, 7, 5, 9, 3, 11, 1, 2, 11 };
var
result = qsort(data);
result.ToList().ForEach(x => Console.WriteLine(x.ToString()));
//排完序后输出
|
最后提供一下官方的C# Lambda表达式的权威资料。C# Lambda表达式