您的位置:首页 > 编程语言 > C#

C# in Depth Third Edition 学习笔记-- Lambda表达式和表达式树

2014-08-07 14:13 761 查看
作为委托的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核心的表达式树:

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