- 作为委托的Lambda表达式:
Func<....>委托类型: 在.Net 3.5中有以下5个
TResult Func<TResult>() TResult Func<T,TResult>(T arg) TResult Func<T1,T2,TResult>(T1 arg1, T2 arg2) TResult Func<T1,T2,T3,TResult>(T1 arg1, T2 arg2, T3 arg3) TResult Func<T1,T2,T3,T4,TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4)
例如Func<string,double,int> 等价于public delegate int SomeDelegate(string arg1, double arg2)。
如果感觉4个参数太少不够用,在.Net 4中Action<.......>和Func<....>最多可以拥有16个参数。
// 使用匿名方法创建委托实例 Func<string,int> returnLength; returnLength = delegate (string text) { return text.Length; }; Console.WriteLine(returnLength("Hello")); // 第一个冗长的Lambda表达式 Func<string,int> returnLength; returnLength = (string text) => { return text.Length; }; Console.WriteLine(returnLength("Hello")); // (显示类型的参数列表)=>表达式 (string text) => text.Length // (隐式类型的参数列表)=>表达式 (text) => text.Length // 参数名=>表达式 text => text.Length
- 使用List<T>和事件的简单例子
class Film { public string Name { get; set; } public int Year { get; set; } } ... var films = new List<Film> { new Film { Name = "Jaws", Year = 1975 }, new Film { Name = "Singing in the Rain", Year = 1952 }, new Film { Name = "Some like it Hot", Year = 1959 }, new Film { Name = "The Wizard of Oz", Year = 1939 }, new Film { Name = "It's a Wonderful Life", Year = 1946 }, new Film { Name = "American Beauty", Year = 1999 }, new Film { Name = "High Fidelity", Year = 2000 }, new Film { Name = "The Usual Suspects", Year = 1995 } }; Action<Film> print = film => Console.WriteLine("Name={0}, Year={1}", film.Name, film.Year); films.ForEach(print); films.FindAll(film => film.Year < 1960).ForEach(print); // 被编译成如下方法
//private static bool SomeAutoGeneratedName(Film film)
//{
//return film.Year < 1960;
//}
films.Sort((f1, f2) => f1.Name.CompareTo(f2.Name)); films.ForEach(print);
- 表达式树Expression trees
code as data将代码作为数据,JIT将IL代码视为数据,并把它们转换成能在某个cpu上运行的本地代码。
以编程方式构建表达式树:
表达式树由对象构成的树,树中每个节点本身就是一个表达式。不同的表达式类型代表能在代码中执行的不同操作:二元操作(例如加法),一元操作(例如获取一个数组的长度),方法调用,构造函数的调用,等等。
一个简单的表达式树,2和3相加
Expression firstArg = Expression.Constant(2); Expression secondArg = Expression.Constant(3); Expression add = Expression.Add(firstArg, secondArg); Console.WriteLine(add);
在表达式树中叶子最先被创建:自下而上构建了这些表达式树。
将表达式树编译成委托:(下面是类的继承关系)
Expression firstArg = Expression.Constant(2); Expression secondArg = Expression.Constant(3); Expression add = Expression.Add(firstArg, secondArg); Func<int> compiled = Expression.Lambda<Func<int>>(add).Compile(); Console.WriteLine(compiled());
将C#lambda表达式转换成表达式树:(下面两段代码是等价的,第二个代码段是使用代码生成的第一个代码段的表达式)
Expression<Func<string, string, bool>> expression = (x, y) => x.StartsWith(y); var compiled = expression.Compile(); Console.WriteLine(compiled("First", "Second")); Console.WriteLine(compiled("First", "Fir"));
MethodInfo method = typeof(string).GetMethod ("StartsWith", new[] { typeof(string) }); var target = Expression.Parameter(typeof(string), "x"); var methodArg = Expression.Parameter(typeof(string), "y"); Expression[] methodArgs = new[] { methodArg }; Expression call = Expression.Call(target, method, methodArgs); var lambdaParameters = new[] { target, methodArg }; var lambda = Expression.Lambda<Func<string, string, bool>> (call, lambdaParameters); var compiled = lambda.Compile(); Console.WriteLine(compiled("First", "Second")); Console.WriteLine(compiled("First", "Fir"));
位于LINQ核心的表达式树: