Lambda Expressions (Lambda表达式)与Expressions Tree(表达式树)

什么是Lambda表达式?我们可以认为它是匿名方法的简洁写法,例如下面这个匿名方法:

1: delegate(int age)

 

2: {

 

3: return age < 18;

 

4: }

 

我们就可以写成Lambda表达式的形式:

1: age => age < 18

 

这是一个很简单的例子,基本上一目了然。Lambda的基本形式是argument-list => expression,=>是Lambda表达式的标识符而不是运算符,显而易见,=>的作用就是{}花括号的作用,与此同时,我们看到了在Lambda表达式中被省略掉的还有参数声明中的数据类型和return关键字以及句尾的分号,因为它们在Lambda表达式中不是必需的,在有参数的情况下表达式总是会返回一个值,而没有参数的情况下表达式也可以不必返回任何值,参数的数据类型是靠编译器从右边的表达式中反推出来的,另外,=>右边只是一个表达式而不是一句完整的语句,所以如果画蛇添足地加上分号就违背了语法规则。当然,右边的表达式中也是可以包含多条语句的,这时候语句之间依然采用分号来分割,但前提是这些语句都要被放置在一对{}花括号里面,不过我的建议还是在语句较少功能较简单的时候才只用Lambda表达式,否则写出来的代码在可读性方面可能会比较差,为以后的维护和修改工作带来不必要的麻烦,要像对待内联函数一样对待Lmbda表达式。

在单个参数的Lambda表达式中我们可以省略参数列表部分的小括号,但是多个参数或者没有参数以及需要显式地为参数设置数据类型的情况下,小括号就不能省略了,例如:

1: // No parameter.

 

2: () => Console.WriteLine("Hello, world!")

 

3:  

 

4: // Multiple parameters.

 

5: (m, n) => m = n * 10

 

6:  

 

7: // Explicitly typed declaration.

 

8: (int age) => age < 18

 

那么我们什么时候用Lambda表达式呢?很简单,前面说过我们可以认为Lambda表达式就是匿名方法的简洁写法,所以原先采用匿名方法的地方现在我们就可以替换成Lambda表达式了。

同样的,如果一些事件发生的时候我们只想做一点儿简单的事情的话,那么也可用Lambda表达式来实现:

1: System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();

 

2: timer.Interval = 2000;

 

3: timer.Tick += (sender, e) => { timer.Stop(); MessageBox.Show("Hello, Lambda Expression!"); };

 

最后我们来看一段比较完整的代码并以此结束对Lambda表达式的介绍吧:

1: using System;

 

2: using System.Collections.Generic;

 

3:  

 

4: namespace LambdaExpressionDemo

 

5: {

 

6: class Program

 

7: {

 

8: private static List<StudentData> _class = null;

 

9:  

 

10: static void Initialization()

 

11: {

 

12: _class = new List<StudentData>();

 

13:  

 

14: _class.Add(new StudentData("ZeroCool", 24, GenderType.Male, 87));

 

15: _class.Add(new StudentData("Michael", 24, GenderType.Male, 93));

 

16: _class.Add(new StudentData("Frieda", 22, GenderType.Female, 98));

 

17: _class.Add(new StudentData("Somebody", 23, GenderType.Male, 81));

 

18: }

 

19:  

 

20: static void Main(string[] args)

 

21: {

 

22: Initialization();

 

23:  

 

24: if (_class == null || _class.Count == 0)

 

25: {

 

26: throw new InvalidOperationException("The system initialization was failed.");

 

27: }

 

28:  

 

29: StudentData studentData = _class.Find(student => student.MathScore >= 90 && student.MathScore < 95);

 

30: RepresentData(studentData);

 

31:  

 

32: studentData = _class.Find(student => student.Name.Equals("ZeroCool", StringComparison.InvariantCultureIgnoreCase));

 

33: RepresentData(studentData);

 

34:  

 

35: studentData = _class.Find(student => student.Age < 23);

 

36: RepresentData(studentData);

 

37:  

 

38: Console.ReadLine();

 

39: }

 

40:  

 

41: static void RepresentData(StudentData student)

 

42: {

 

43: if (student == null)

 

44: {

 

45: Console.WriteLine("No mached student.");

 

46:  

 

47: return;

 

48: }

 

49:  

 

50: Console.WriteLine("Name:tt" + student.Name);

 

51: Console.WriteLine("Age:tt" + student.Age);

 

52: Console.WriteLine("Gender:tt" + student.Gender.ToString());

 

53: Console.WriteLine("Math Score:t" + student.MathScore);

 

54: Console.WriteLine();

 

55: }

 

56: }

 

57:  

 

58: public enum GenderType

 

59: {

 

60: Male = 0,

 

61: Female

 

62: }

 

63:  

 

64: public class StudentData

 

65: {

 

66: private string _name = String.Empty;

 

67: public string Name

 

68: {

 

69: get { return this._name; }

 

70: set { this._name = value; }

 

71: }

 

72:  

 

73: private int _age = 0;

 

74: public int Age

 

75: {

 

76: get { return this._age; }

 

77: set { this._age = value; }

 

78: }

 

79:  

 

80: private GenderType _gender;

 

81: public GenderType Gender

 

82: {

 

83: get { return this._gender; }

 

84: set { this._gender = value; }

 

85: }

 

86:  

 

87: private int _mathScore = 0;

 

88: public int MathScore

 

89: {

 

90: get { return this._mathScore; }

 

91: set { this._mathScore = value; }

 

92: }

 

93:  

 

94: public StudentData()

 

95: {

 

96: }

 

97:  

 

98: public StudentData(string name, int age, GenderType gender, int mathScore)

 

99: {

 

100: this._name = name;

 

101: this._age = age;

 

102: this._gender = gender;

 

103: this._mathScore = mathScore;

 

104: }

 

105:  

 

106: public delegate void EmptyDelegate();

 

107:  

 

108: EmptyDelegate dl = () => Console.WriteLine();

 

109: }

 

110: }

 

上面的代码肯定还有不够完善的地方,肯定还可以被再次提炼、加工,那么就留给各位网友仁者见仁,智者见智吧。好了,Lambda表达式大概就介绍到这里,接下来我们一起来探讨一下表达式树吧。

表达式树典型的声明形式是:

1: Func<int, int> func = input => input * input;

 

2: Expression<Func<int, int>> expression = input => input * input;

 

我们必须要使用的类型是System.Linq.Expressions命名空间中的Expression<T>,而这个T是定义表达式签名的委托的类型,这种把一个Lambda表达式看做一个数据结构而嵌套在另一个Lambda表达式中的做法使得现在的expression不是一个委托而是表达式树的数据结构了。接下来的问题是我们应该如何使用这个表达式树呢?请看完整的代码:

1: static void Main(string[] args)

 

2: {

 

3: Func<int, int> func = input => input * input;

 

4: Console.WriteLine(func(3).ToString());

 

5:  

 

6: Expression<Func<int, int>> expression = input => input * input;

 

7: Func<int, int> fun = expression.Compile();

 

8: Console.WriteLine(fun(5).ToString());

 

9:  

 

10: Console.ReadLine();

 

11: }

 

正因为func是可执行代码而expression是数据,所以在使用方式上也会有所差别的,希望以上这些代码可以很好地让你理解Lambda表达式以及表达式树这两个概念。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值