用excel 做网站,画册怎么做,设计网红打卡,wordpress二次元源码转载自诗人江湖老,原文地址 C#在执行LINQ查询表达式的时候#xff0c;并不会指定其执行语义#xff0c;而是将查询表达式转换为遵循查询表达式模式的方法的调用。具体而言#xff0c;查询表达式将转换为以下名称的调用#xff1a;Where、Select、SelectMany、Join、GroupJo…转载自诗人江湖老,原文地址 C#在执行LINQ查询表达式的时候并不会指定其执行语义而是将查询表达式转换为遵循查询表达式模式的方法的调用。具体而言查询表达式将转换为以下名称的调用Where、Select、SelectMany、Join、GroupJoin、OrderBy、OrderByDescending、ThenBy、ThenByDescending、GroupBy、Cast等等。 如同在前文中提到的用扩展方法和Lambda表达式简化LINQ查询表达式一般这也是对查询表达式的一种转换。简化后的方法其实就是LINQ查询的实际执行。 本文中用来示例的代码参数设定都沿用上一篇文章的设定。
转换规则简述 从查询表达式到方法调用的转换是一种句法映射在执行任何类型绑定或重载决策之前发生。该转换可以保证在句法上正确但不能保证生成语法正确的 C# 代码。转换查询表达式后以常规方法调用的方式处理生成的方法调用而这进而可能暴露错误例如在方法不存在、参数类型错误或方法为泛型方法且类型推断失败这些情况下。 不允许对查询表达式中的范围变量进行赋值。但允许 C# 实现在某些时候以不实施此限制因为对于此处介绍的句法转换方案有些时候可能根本无法实施此限制。 某些转换使用由 * 指示的透明标识符注入范围变量。
转换规则讲解
带继续符的select和groupby子句的查询表达式的转换 继续符是指 into 操作符带有继续符的查询表达式类似如下 from ···into x ··· 转换为 from x in (from ···) ··· 示例
from c in customersgroup c by c.Country into g
select new { Countryc.Country , Customer g.Count()} 转换为
from g infrom c in customersgroup c by c.Country
select new { Country g.Key, CustCount g.Count() } 最终转换为
customers.
GroupBy(c c.Country).
Select(g new { Country g.Key, CustCount g.Count() })
含有显式范围变量类型的查询表达式的转换 显式指定范围变量类型的 from 子句 from T x in e 转换为 from x in e.CastT() 显式指定范围变量类型的 join 子句 join T x in e on k1 equals k2 转换为 join x in e.CastT() 示例
from Customer in customers
where c.City London
select c 转换为
from c in customers.CastCustomer()
where c.City London
select c 最终转换为
customers.CastCustomer().Where(cc.CityLondon) 显式范围变量类型对于查询实现非泛型 IEnumerable 接口的集合很有用但对于实现泛型IEnumerable 接口的集合没什么用处。如果 customers 属于 ArrayList 类型则在面的示例中即会如此。
退化查询表达式的转换 退化查询表达式是指选择源元素本身的查询如
from c in customers
select c 确保查询表达式的结果永不为源对象本身非常重要因为这样会向查询的客户端暴露源的类型和标识符。因此在查询表达式为退化查询的时候可通过在源上显式调用 Select 来保护直接以源代码形式写入的简并查询。然后由 Select 实施者及其他查询操作员确保这些方法永远不会返回源对象本身。 退化查询表达式如下 from x in e select x 转换为 e.Select(xx) 示例
from c in customers
select c 转换为
customers.Select(c c)
from、 let、 where、 join 和 orderby 子句的转换
转换规则 带有另一个 from 子句且后接一个 select 子句的查询表达式 from x1 in e1 from x2 in e2 select v 转换为 e1.SelectMany( x1 e2 , ( x1 , x2 ) v ) 带有另一个 from 子句且后接一个 select 子句的查询表达式 from x1 in e1 from x2 in e2 ··· 转换为 from * in e1.SelectMany( x1 e2 , ( x1 , x2 ) new { x1 , x2 }) 带有 let 子句的查询表达式 from x in e let yf 转换为 from * in e.Select( x new { x , y f }) 带有 where 子句的查询表达式 from x in e where f ··· 转换为 from x in e.Where( x f ) 带有 join 子句不含 into且后接 select 子句的查询表达式 from x1 in e1 join x2 in e2 on k1 equals k2 select v 转换为 ( e1 ) . Join( e2 , x1 k1 , x2 k2 , ( x1 , x2 ) v ) 带有 join 子句不含 into且后接除 select 子句之外的其他内容的查询表达式 from x1 in e1 join x2 in e2 on k1 equals k2 … 转换为 from * in ( e1 ) . Join( e2 , x1 k1 , x2 k2 , ( x1 , x2 ) new { x1 , x2 }) … 带有 join 子句含 into且后接 select 子句的查询表达式 from x1 in e1 join x2 in e2 on k1 equals k2 into g select v 转换为 ( e1 ) . GroupJoin( e2 , x1 k1 , x2 k2 , ( x1 , g ) v ) 带有 join 子句含 into且后接除 select 子句之外的其他内容的查询表达式 from x1 in e1 join x2 in e2 on k1 equals k2 into g … 转换为 from * in ( e1 ) . GroupJoin( e2 , x1 k1 , x2 k2 , ( x1 , g ) new { x1 , g }) … 带有 orderby 子句的查询表达式 from x in e orderby k1 , k2 , … , kn … 转换为 from x in ( e ) . OrderBy ( x k1 ) . ThenBy ( x k2 ). … . ThenBy ( x kn ) … 如果排序子句指定 descending 方向指示器则将改为生成对 OrderByDescending 或 ThenByDescending 的调用。
转换规则实例演示 我们假定在下面的每个查询表达式中没有 let、 where、 join 或 orderby 子句并且最多只有一个初始 from 子句。 示例1 from c in customersfrom o in c.Ordersselect new { c.Name, o.OrderID, o.Total } 转换为
customers.
SelectMany(c c.Orders,(c,o) new { c.Name, o.OrderID, o.Total })12 示例2
from c in customers
from o in c.Orders
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total } 转换为
from * in customers.SelectMany(c c.Orders, (c,o) new { c, o })
orderby o.Total descending
select new { c.Name, o.OrderID, o.Total } 最终转换为
customers.SelectMany(c c.Orders, (c,o) new { c, o }).OrderByDescending(x x.o.Total).Select(x new { x.c.Name, x.o.OrderID, x.o.Total }) 其中 x 是编译器生成的以其他方式不可见且不可访问的标识符。 示例3
from o in orders
let t o.Details.Sum(d d.UnitPrice * d.Quantity)
where t 1000
select new { o.OrderID, Total t } 转换为
from * in orders.
Select(o new { o, t o.Details.Sum(d d.UnitPrice * d.Quantity) })
where t 1000
select new { o.OrderID, Total t } 最终转换为
orders.Select(o new { o, t o.Details.Sum(d d.UnitPrice * d.Quantity) }).Where(x x.t 1000).Select(x new { x.o.OrderID, Total x.t }) 其中 x 是编译器生成的以其他方式不可见且不可访问的标识符。 示例4
from c in customers
join o in orders on c.CustomerID equals o.CustomerID
select new { c.Name, o.OrderDate, o.Total } 转换为
customers.Join(orders, c c.CustomerID, o o.CustomerID,(c, o) new { c.Name, o.OrderDate, o.Total }) 示例5
from c in customers
join o in orders on c.CustomerID equals o.CustomerID into co
let n co.Count()
where n 10
select new { c.Name, OrderCount n } 转换为
from * in customers.GroupJoin(orders, c c.CustomerID, o o.CustomerID,
(c, co) new { c, co })
let n co.Count()
where n 10
select new { c.Name, OrderCount n } 最终转换为
customers.GroupJoin(orders, c c.CustomerID, o o.CustomerID,(c, co) new { c, co }).Select(x new { x, n x.co.Count() }).Where(y y.n 10).Select(y new { y.x.c.Name, OrderCount y.n) 其中 x 和 y 是编译器生成的以其他方式不可见且不可访问的标识符。 示例6
from o in orders
orderby o.Customer.Name, o.Total descending
select o 转换为
orders.OrderBy(o o.Customer.Name).ThenByDescending(o o.Total) select 子句的转换 from x in e select v 转换为 ( e ) . Select ( x v ) 当 v 为标识符 x 时转换仅为 ( e ) Groupby 子句的转换 from x in e group v by k 转换为 ( e ) . GroupBy ( x k , x v ) 当 v 为标识符 x 时转换为 ( e ) . GroupBy ( x k )