您的位置:首页 > 其它

.NET 3.x新特性之Lambda表达式

2015-05-08 10:11 357 查看
.NET 3.x新特性之Lambda表达式

lambda 表达式格式为:

(参数列表) => 表达式或者语句块

分为三个步骤

1、(参数列表):

2、=>符号可以理解为从

3、表达式或者语句块

可以有多个参数,一个参数,或者无参数。参数类型可以隐失或者显示。例如:

(x,y) => x * y //多参数,隐式类型=>表达式

x => x * 10 //单参数,隐式类型=>表达式

x => {return x * 10;} //单参数,隐失类型=>语句块

(int x) => x * 10 //单参数,显示类型=>表达式

(int x) => {return x * 10} //单参数,显示类型=>语句块

() => Console.WriteLing() //无参数

Lambda表达式其实是一个委托类型实例,编译器会根据参数的类型建立一个同类型的同参数的委托:

比如

x => x * 10

相当于是下面一个委托类型的实例

delegate int MyDeg(int i);//这个是由编译器根据推断出的类型而建立的

只不过这些工作由编译器帮我们做了

Lambda 表达式格式要点

- Lambda表达式的参数类型可以忽略,因为可以根据使用的上下文进行推断。

- Lambda表达式的主体(body)可以是表达式,也可以是语句块。

- Lambda表达式传入的实参将参与类型推断,以及方法重载辨析。

- Lambda表达式和表达式体可以被转换为表达式树。

Lambda 表达式与委托类型

Lambda 表达式L可以被转换为委托类型D,需要满足以下条件:

- L和D拥有相同的参数个数。

- L的参数类型要与D的的参数类型相同。注意隐式类型要参与类型辨析。

- D的返回类型与L相同,无论L是表达式,还是语句块。

下面我们来看一下编译器到底都做了些什么?

比如在程序中有下面Lambda表达式:

delegate bool Mydelegate(string s);

class jh

{

public static Process(Mydelegate myd)

{

myd("wo shi jhxz");

}

}

jh.Process(s => s.Indexof("jhxz") > 0) //Process方法接受一个Mydelegate的委托

编译其实有Lambda表达式那条语句编译为以下这样的代码:

Mydelegate md=new Mydelegate(IsValidXXXX);//编译器生成

jh.Process(md1)

public static bool IsValidXXXX(string s)//编译器生成

{

  return s.Indexof("jhxz") > 0;

}

体验:

1.准备测试数据

static int[] numbers = new int[] { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };

static string[] strings = new string[] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};

class Person {

public string Name;

public int Level;

}

static Person[] persons = new Person[] {

new Person {Name="Matt", Level=3},

new Person {Name="Luca", Level=3},

new Person {Name="Jomo", Level=5},

new Person {Name="Dinesh", Level=3},

new Person {Name="Charlie", Level=3},

new Person {Name="Mads", Level=3},

new Person {Name="Anders", Level=9}

};

2.过滤数据

public static void Sample1() {

// use Where() to filter out elements matching a particular condition

IEnumerable<int> fnums = numbers.Where(n => n < 5);

Console.WriteLine("Numbers < 5");

foreach(int x in fnums) {

Console.WriteLine(x);

}

}

3.匹配首个字母

public static void Sample2() {

// use First() to find the one element matching a particular condition

string v = strings.First(s => s[0] == 'o');

Console.WriteLine("string starting with 'o': {0}", v);

}

4.根据numbers排序

public static void Sample3() {

// use Select() to convert each element into a new value

IEnumerable<string> snums = numbers.Select(n => strings
);

Console.WriteLine("Numbers");

foreach(string s in snums) {

Console.WriteLine(s);

}

}

5.匿名类型,注意var关键字

public static void Sample4()

{

// use Anonymous Type constructors to construct multi-valued results on the fly

var q = strings.Select(s => new {Head = s.Substring(0,1), Tail = s.Substring(1)});

foreach(var p in q) {

Console.WriteLine("Head = {0}, Tail = {1}", p.Head, p.Tail);

}

}

6.联合查询(即使用两个以上的查询条件)

public static void Sample5() {

// Combine Select() and Where() to make a complete query

var q = numbers.Where(n => n < 5).Select(n => strings
);

Console.WriteLine("Numbers < 5");

foreach(var x in q) {

Console.WriteLine(x);

}

}

7.使用ToList方法

public static void Sample6() {

// Sequence operators form first-class queries are not executed until you enumerate them.

int i = 0;

var q = numbers.Select(n => ++i);

// Note, the local variable 'i' is not incremented until each element is evaluated (as a side-effect).

foreach(var v in q) {

Console.WriteLine("v = {0}, i = {1}", v, i);

}

Console.WriteLine();

// Methods like ToList() cause the query to be executed immediately, caching the results

int i2 = 0;

var q2 = numbers.Select(n => ++i2).ToList();

// The local variable i2 has already been fully incremented before we iterate the results

foreach(var v in q2) {

Console.WriteLine("v = {0}, i2 = {1}", v, i2);

}

}

8.分组查询

public static void Sample7() {

// use GroupBy() to construct group partitions out of similar elements

var q = strings.GroupBy(s => s[0]); // <- group by first character of each string

foreach(var g in q) {

Console.WriteLine("Group: {0}", g.Key);

foreach(string v in g) {

Console.WriteLine("\tValue: {0}", v);

}

}

}

9.统计聚合

public static void Sample8() {

// use GroupBy() and aggregates such as Count(), Min(), Max(), Sum(), Average() to compute values over a partition

var q = strings.GroupBy(s => s[0]).Select(g => new {FirstChar = g.Key, Count = g.Count()});

foreach(var v in q) {

Console.WriteLine("There are {0} string(s) starting with the letter {1}", v.Count, v.FirstChar);

}

}

10.排序

// use OrderBy()/OrderByDescending() to give order to your resulting sequence

var q = strings.OrderBy(s => s); // order the strings by their name

foreach(string s in q) {

Console.WriteLine(s);

}

}

11.二次排序

public static void Sample9a() {

// use ThenBy()/ThenByDescending() to provide additional ordering detail

var q = persons.OrderBy(p => p.Level).ThenBy(p => p.Name);

foreach(var p in q) {

Console.WriteLine("{0} {1}", p.Level, p.Name);

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Lambda