日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

[深入学习C#]LINQ查询表达式详解(2)——查询表达式的转换

發(fā)布時(shí)間:2025/3/11 C# 47 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [深入学习C#]LINQ查询表达式详解(2)——查询表达式的转换 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

轉(zhuǎn)載自詩人江湖老,原文地址

  C#在執(zhí)行LINQ查詢表達(dá)式的時(shí)候,并不會(huì)指定其執(zhí)行語義,而是將查詢表達(dá)式轉(zhuǎn)換為遵循查詢表達(dá)式模式的方法的調(diào)用。具體而言,查詢表達(dá)式將轉(zhuǎn)換為以下名稱的調(diào)用:Where、Select、SelectMany、Join、GroupJoin、OrderBy、OrderByDescending、ThenBy、ThenByDescending、GroupBy、Cast等等。
  如同在前文中提到的用擴(kuò)展方法和Lambda表達(dá)式簡(jiǎn)化LINQ查詢表達(dá)式一般,這也是對(duì)查詢表達(dá)式的一種轉(zhuǎn)換。簡(jiǎn)化后的方法其實(shí)就是LINQ查詢的實(shí)際執(zhí)行。
  本文中用來示例的代碼,參數(shù)設(shè)定都沿用上一篇文章的設(shè)定。

轉(zhuǎn)換規(guī)則簡(jiǎn)述

  從查詢表達(dá)式到方法調(diào)用的轉(zhuǎn)換是一種句法映射,在執(zhí)行任何類型綁定或重載決策之前發(fā)生。該轉(zhuǎn)換可以保證在句法上正確,但不能保證生成語法正確的 C# 代碼。轉(zhuǎn)換查詢表達(dá)式后,以常規(guī)方法調(diào)用的方式處理生成的方法調(diào)用,而這進(jìn)而可能暴露錯(cuò)誤,例如在方法不存在、參數(shù)類型錯(cuò)誤或方法為泛型方法且類型推斷失敗這些情況下。
  不允許對(duì)查詢表達(dá)式中的范圍變量進(jìn)行賦值。但允許 C# 實(shí)現(xiàn)在某些時(shí)候以不實(shí)施此限制,因?yàn)閷?duì)于此處介紹的句法轉(zhuǎn)換方案,有些時(shí)候可能根本無法實(shí)施此限制。
  某些轉(zhuǎn)換使用由 * 指示的透明標(biāo)識(shí)符注入范圍變量。

轉(zhuǎn)換規(guī)則講解

帶繼續(xù)符的select和groupby子句的查詢表達(dá)式的轉(zhuǎn)換

  繼續(xù)符是指 into 操作符,帶有繼續(xù)符的查詢表達(dá)式類似如下:
   from ···into x ···
   轉(zhuǎn)換為
   from x in (from ···) ···
   示例:

from c in customersgroup c by c.Country into g select new { Country=c.Country , Customer = g.Count()}

   轉(zhuǎn)換為

from g infrom c in customersgroup c by c.Country select new { Country = g.Key, CustCount = g.Count() }

   最終轉(zhuǎn)換為 

customers. GroupBy(c => c.Country). Select(g => new { Country = g.Key, CustCount = g.Count() })

含有顯式范圍變量類型的查詢表達(dá)式的轉(zhuǎn)換

   顯式指定范圍變量類型的 from 子句
   from T x in e
   轉(zhuǎn)換為
   from x in (e).Cast<T>()

   顯式指定范圍變量類型的 join 子句
   join T x in e on k1 equals k2
   轉(zhuǎn)換為
   join x in (e).Cast<T>()

   示例: 

from Customer in customers where c.City == "London" select c

   轉(zhuǎn)換為

from c in customers.Cast<Customer>() where c.City == "London" select c

   最終轉(zhuǎn)換為

customers.Cast<Customer>().Where(c=>c.City=="London")>

   顯式范圍變量類型對(duì)于查詢實(shí)現(xiàn)非泛型 IEnumerable 接口的集合很有用,但對(duì)于實(shí)現(xiàn)泛型IEnumerable 接口的集合沒什么用處。如果 customers 屬于 ArrayList 類型,則在面的示例中即會(huì)如此。
  

退化查詢表達(dá)式的轉(zhuǎn)換

   退化查詢表達(dá)式,是指選擇源元素本身的查詢,如:

from c in customers select c

  確保查詢表達(dá)式的結(jié)果永不為源對(duì)象本身非常重要,因?yàn)檫@樣會(huì)向查詢的客戶端暴露源的類型和標(biāo)識(shí)符。因此,在查詢表達(dá)式為退化查詢的時(shí)候,可通過在源上顯式調(diào)用 Select 來保護(hù)直接以源代碼形式寫入的簡(jiǎn)并查詢。然后,由 Select 實(shí)施者及其他查詢操作員確保這些方法永遠(yuǎn)不會(huì)返回源對(duì)象本身。

  退化查詢表達(dá)式如下:
  from x in e select x
  轉(zhuǎn)換為
  (e).Select(x=>x)
  示例:

from c in customers select c

  轉(zhuǎn)換為

customers.Select(c => c)

from、 let、 where、 join 和 orderby 子句的轉(zhuǎn)換

轉(zhuǎn)換規(guī)則

  帶有另一個(gè) from 子句且后接一個(gè) select 子句的查詢表達(dá)式
  from x1 in e1
  from x2 in e2
  select v
  轉(zhuǎn)換為
  (e1).SelectMany( x1 => e2 , ( x1 , x2 ) => v )

  帶有另一個(gè) from 子句且后接一個(gè) select 子句的查詢表達(dá)式
  from x1 in e1
  from x2 in e2
  ···
  轉(zhuǎn)換為
  from * in (e1).SelectMany( x1 => e2 , ( x1 , x2 ) => new { x1 , x2 })

  帶有 let 子句的查詢表達(dá)式
  from x in e
  let y=f
  轉(zhuǎn)換為
  from * in (e).Select( x => new { x , y = f })

  帶有 where 子句的查詢表達(dá)式
  from x in e
  where f
  ···
  轉(zhuǎn)換為
  from x in (e).Where( x => f )

  帶有 join 子句(不含 into)且后接 select 子句的查詢表達(dá)式
  from x1 in e1
  join x2 in e2 on k1 equals k2
  select v
  轉(zhuǎn)換為
  ( e1 ) . Join( e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => v )

  帶有 join 子句(不含 into)且后接除 select 子句之外的其他內(nèi)容的查詢表達(dá)式
  from x1 in e1
  join x2 in e2 on k1 equals k2
  
  轉(zhuǎn)換為
  from * in ( e1 ) . Join(
  e2 , x1 => k1 , x2 => k2 , ( x1 , x2 ) => new { x1 , x2 })
  

  帶有 join 子句(含 into)且后接 select 子句的查詢表達(dá)式
  from x1 in e1
  join x2 in e2 on k1 equals k2 into g
  select v
  轉(zhuǎn)換為
  ( e1 ) . GroupJoin( e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => v )
  
  帶有 join 子句(含 into)且后接除 select 子句之外的其他內(nèi)容的查詢表達(dá)式
  from x1 in e1
  join x2 in e2 on k1 equals k2 into g
  
  轉(zhuǎn)換為
  from * in ( e1 ) . GroupJoin(
  e2 , x1 => k1 , x2 => k2 , ( x1 , g ) => new { x1 , g })
  

  帶有 orderby 子句的查詢表達(dá)式
  from x in e
  orderby k1 , k2 , … , kn
  
  轉(zhuǎn)換為
  from x in ( e ) .
  OrderBy ( x => k1 ) .
  ThenBy ( x => k2 ).
  … .
  ThenBy ( x => kn )
  
  如果排序子句指定 descending 方向指示器,則將改為生成對(duì) OrderByDescending 或
ThenByDescending 的調(diào)用。

轉(zhuǎn)換規(guī)則實(shí)例演示

  我們假定,在下面的每個(gè)查詢表達(dá)式中沒有 let、 where、 join 或 orderby 子句,并且最多只有一個(gè)初始 from 子句。
  
  示例1:

  from c in customersfrom o in c.Ordersselect new { c.Name, o.OrderID, o.Total }

  轉(zhuǎn)換為

customers. SelectMany(c => c.Orders,(c,o) => new { c.Name, o.OrderID, o.Total })
  • 1
  • 2

  
  示例2:  

from c in customers from o in c.Orders orderby o.Total descending select new { c.Name, o.OrderID, o.Total }

  轉(zhuǎn)換為

from * in customers.SelectMany(c => c.Orders, (c,o) => new { c, o }) orderby o.Total descending select new { c.Name, o.OrderID, o.Total }

  最終轉(zhuǎn)換為

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 是編譯器生成的以其他方式不可見且不可訪問的標(biāo)識(shí)符。

  
  示例3:

from o in orders let t = o.Details.Sum(d => d.UnitPrice * d.Quantity) where t >= 1000 select new { o.OrderID, Total = t }

  轉(zhuǎn)換為

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 }

  最終轉(zhuǎn)換為

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 是編譯器生成的以其他方式不可見且不可訪問的標(biāo)識(shí)符。

  示例4:

from c in customers join o in orders on c.CustomerID equals o.CustomerID select new { c.Name, o.OrderDate, o.Total }

  轉(zhuǎn)換為

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 }

  轉(zhuǎ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 }

  最終轉(zhuǎ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 是編譯器生成的以其他方式不可見且不可訪問的標(biāo)識(shí)符。
  
  示例6:

from o in orders orderby o.Customer.Name, o.Total descending select o

  轉(zhuǎn)換為

orders.OrderBy(o => o.Customer.Name).ThenByDescending(o => o.Total)

select 子句的轉(zhuǎn)換

  from x in e select v
  轉(zhuǎn)換為
  ( e ) . Select ( x => v )
  當(dāng) v 為標(biāo)識(shí)符 x 時(shí),轉(zhuǎn)換僅為
  ( e )
  

Groupby 子句的轉(zhuǎn)換

  from x in e group v by k
  轉(zhuǎn)換為
  ( e ) . GroupBy ( x => k , x => v )
  當(dāng) v 為標(biāo)識(shí)符 x 時(shí),轉(zhuǎn)換為
  ( e ) . GroupBy ( x => k )

總結(jié)

以上是生活随笔為你收集整理的[深入学习C#]LINQ查询表达式详解(2)——查询表达式的转换的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。