不一样的编码风格--Lambda表达式
Lambda表达式也是C#3.0中最重要的特性之一。
1、Lambda表达式的简介
Lambda表达式可以理解为一个匿名方法,它可以包含表达式和语句,并且用于创建委托或转换为表达式树。在使用Lambda表达式时,都会使用“=>”运算符,该运算符的左边是匿名方法的输入参数,右边则是表达式或语句块。
1.1 Lambda表达式的演变过程
其实Lambda表达式是匿名方法的投胎转世。下面以代码来鉴定:
1 C# 1.0 2 Func<string,int> delegatetest1=new Func<string,int>(Callbackmethod); 3 4 C# 2.0 5 Func<string,int> delegatetest2=delegate(string text) 6 { 7 return text.Length; 8 } 9 10 C# 3.0 11 Func<string,int> delegatetest3=(string text)=>text.Length; 12 13 可以省略参数类型string,从而将代码再次简化 14 Func<string,int> delegatetest4=(text)=text.Length; 15 此时也可以把圆括号省略 16 Func<string,int> delegatetest=text=>text.Length;
以上代码形象地掩饰了Lambda表达式是如何由匿名方法演变而来的。
1.2 Lambda表达式的使用
在实际开发过程中,委托的用途莫过于订阅事件了。为了加深大家对Lambda表达式的理解,这里选择演示用Lambda表达式去订阅事件。
1 namespace Lambda表达式 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 Button button1 = new Button() {Text = "点击我"}; 8 button1.Click += (sender, e) => ReportEvent("Click事件", sender, e); 9 button1.KeyPress += (sender, e) => ReportEvent("KeyPress事件", sender, e); 10 } 11 12 private static void ReportEvent(string s, object sender, EventArgs eventArgs) 13 { 14 throw new NotImplementedException(); 15 } 16 } 17 }
从以上代码可以看出,使用了C# 3.0的对象初始化器和Lambda表达式后,代码确实简洁了不少。
2、表达式也有树结构——表达式树
Lambda表达式除了可以用来创建委托外,还可以转换成表达式树。表达式树(或称“表达式目录树”)是用来表示Lambda表达式逻辑的一种数据结构,它将代码表示成一个对象树,而非可执行代码。其实可以将表达式树理解为一种数据结构,类似栈或队列这种。
2.1 通过Lambda表达式来构造表达式树
1 namespace 表达式树 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 //将Lambda表达式构造成表达式树 8 Expression<Func<int, int, int>> expressionTree = (a, b) => a + b; 9 10 //获得表达式树参数 11 Console.WriteLine($"参数1:{expressionTree.Parameters[0]},参数2:{expressionTree.Parameters[1]}"); 12 13 //获取表达式树的主体部分 14 BinaryExpression body = (BinaryExpression) expressionTree.Body; 15 16 //左节点(每个节点本身就是一个表达式对象) 17 ParameterExpression left = (ParameterExpression) body.Left; 18 19 //右节点 20 ParameterExpression right = (ParameterExpression)body.Right; 21 22 Console.WriteLine("表达式树主体为:"); 23 Console.WriteLine(expressionTree.Body); 24 Console.WriteLine($"表达式树左节点为:{left.Name}{Environment.NewLine} 节点类型为:{left.Type}{Environment.NewLine}{Environment.NewLine} 表达式树右节点为:{right.Name}{Environment.NewLine} 节点类型为:{right.Type}{Environment.NewLine}"); 25 Console.ReadKey(); 26 27 } 28 } 29 }
从以上代码可以看出,通过Lambda表达式来构造表达式树的过程非常简单,只需要把Lambda表达式赋给一个表达式树变量就可以了。
2.2 如何把表达式树转换成可执行代码
1 namespace 表达式树2 2 { 3 class Program 4 { 5 static void Main(string[] args) 6 { 7 //将Lambda表达式构造成表达式树 8 Expression<Func<int, int, int>> expressionTree = (a, b) => a + b; 9 //通过调用complie方法来生成Lambda表达式的委托 10 Func<int, int, int> delinstance = expressionTree.Compile(); 11 //调用委托实例获得结果 12 int result = delinstance(1, 2); 13 Console.WriteLine($"2和3的和为:{result}"); 14 Console.ReadKey(); 15 } 16 } 17 }
以上代码通过Expression<TDelegate>类的Compile()方法将表达式树编译成委托实例,然后通过委托调用的方式得到两个数的和。