class OrderUsersByLengthOfNameWithLet { static void Main() { var query = from user in SampleData.AllUsers let length = user.Name.Length //{User: Tim Trotter (Tester)} //{User: Tara Tutu (Tester)} //{User: Deborah Denton (Developer)} //{User: Darren Dahlia (Developer)} //{User: Mary Malcop (Manager)} //{User: Colin Carton (Customer)} orderby length //{User: Tim Trotter (Tester)} 11 //{User: Tara Tutu (Tester)} 9 //{User: Deborah Denton (Developer)} 14 //{User: Darren Dahlia (Developer)} 13 //{User: Mary Malcop (Manager)} 11 //{User: Colin Carton (Customer)} 12 //{User: Tara Tutu (Tester)} 9 select new { Name = user.Name, Length = length }; //{System.Linq.Enumerable.WhereSelectEnumerableIterator<<>f__AnonymousType10<Model.User,int>,<>f__AnonymousType11<string,int>>} foreach (var entry in query) //{ Name = "Tara Tutu", Length = 9 } //{ Name = "Tim Trotter", Length = 11 } //{ Name = "Mary Malcop", Length = 11 } //{ Name = "Colin Carton", Length = 12 } //{ Name = "Darren Dahlia", Length = 13 } //{ Name = "Deborah Denton", Length = 14 } { Console.WriteLine("{0}: {1}", entry.Length, entry.Name); } } }
let对一个表达式进行求值,引入一个新的范围变量。对用户只使用了一次Length
属性
引入了一个名为length的范围变量,包含用户名的长度(针对原始序列中的当前
用户)。我们接着把新的范围变量用于排序和最后的投影。使用了两个范围变量,
但Lambda表达式只会给Select传递一个参数。因为透明标识符,所以传递一个
参数。
如何把范围变量合并到一起,创建一个匿名类型包含两个变量,不过需要一个巧妙的
转换,以便看起来就像在select和orderby子句实际应用了两个参数。
let再一次调用了Select,并为结果序列创建匿名类型,最终创建了一个新的范围变量
查询的每个部分都进行了适当的调整:对于原始的查询表达式直接引用user或
length的地方,如果引用发生在let子句之后,就用z.user或z.length来代替。这里
z这个名称是随机选择的--被编译器隐藏起来。
输出
9: Tara Tutu
11: Tim Trotter
11: Mary Malcop
12: Colin Carton
13: Darren Dahlia
14: Deborah Denton