第 98 講:C# 3 之查詢表達(dá)式(二):let 關(guān)鍵字
歡迎收看查詢表達(dá)式第二集:let
關(guān)鍵字。
Part 1 let
從句:解決 select-into
的副作用
之前我們學(xué)習(xí)了 select
從句,以及 into
用于接續(xù) select
的內(nèi)容??墒?,有些時候使用起來其實(shí)并不方便,因?yàn)?into
會直接阻斷前面的計(jì)算結(jié)果,導(dǎo)致 into
后面的東西不能用 into
前面的東西。
為了解決這個問題,let
從句就出現(xiàn)了。let
用在 from
和 select
期間,表示臨時定義一個新的變量,存儲結(jié)果。和 from
差不多,let
期間也可以多次使用。它的語法是這樣的:
?let 從句
? ? ?'let' 變量名 '=' 表達(dá)式
可以從這樣的語法定義看出,它和 select-into
不一樣的地方在于,變量名稱定義在前面而不是后面。select-into
是將變量名放在 into
后的,而 into
又是放在 select
從句后的,所以是后置;但是 let
從句就更為“好讀”一些。
具體情況,比如下面用到了 let
從句的例子。
into
第 6 行開始的話,因?yàn)樗懊嬗幸粋€ into
從句,而 into
會阻斷表達(dá)式,因此第 5 行以前定義的范圍變量全部無法在第 6 行開始的后續(xù)部分使用。因此,這樣的語法限制下,上述代碼就有問題了,因?yàn)榈?8 行用到了 student
變量。
可以從這里看出,let
從句是一個非常方便的代碼處理機(jī)制,它避免了我們無法定義臨時變量導(dǎo)致表達(dá)式冗長的情況。不過 let
從句也需要你注意一個地方。let
從句用作定義臨時變量,因此它不能放在末尾。換句話說,目前還是只能有 select
從句來結(jié)尾查詢表達(dá)式。即使我們知道,let
從句有些時候得到的結(jié)果已經(jīng)是拿來反饋出來的了:
你仍然需要追加一個 select
從句來補(bǔ)全語法。
Part 2 select-into
從句和 let
從句的區(qū)別
select-into
從句的這種設(shè)計(jì)也不是沒有道理,因?yàn)樗哪康牟⒉皇菫榱巳ゼ哟缶幾g器分析代碼的難度,而是故意為之。它的存在性在于“總結(jié)和摒棄前面的計(jì)算過程,而只保留結(jié)果”。
考慮一下,要是我只想將這些學(xué)生的成績平均分計(jì)算出來,然后只給我一個通過與否的映射表的話,那么我們就不必考慮使用前面的所有臨時變量的處理過程了:
into
從句會阻斷變量的可見范圍,因此這樣疊加的 select-into
是的,select-into
比較方便的地方在于,它可以完全拆解為三個變量,并且互相不牽連。這正是 select-into
的本質(zhì):查詢表達(dá)式的可拆解性。如果你使用前面 let
語句的話,你明顯可以發(fā)現(xiàn),拆解是拆解不了的,因?yàn)?let
從句后會用到 let
前面的范圍變量。如果走 let
從句作為“分水嶺”直接拆開查詢表達(dá)式的話,是肯定做不到的。
所以,select-into
從句的出現(xiàn)是為了使用內(nèi)聯(lián)語法代替掉嵌套查詢。嵌套查詢?前面的寫法不是嵌套查詢?。靠雌饋泶_實(shí)不太像哈。不過,我們?nèi)绻炎兞績?nèi)聯(lián)起來呢,比如把 scores
變量寫到第二個查詢表達(dá)式里代替掉 scores
,然后把 averages
的表達(dá)式寫到第三個查詢表達(dá)式的 averages
上代替掉呢?
是不是就是嵌套查詢呢?所以,這就是 select-into
和 let
從句的區(qū)別了。
Part 3 select-into
和 let
從句在使用期間的選取
那么,什么時候用什么從句呢?
其實(shí)你可以發(fā)現(xiàn),兩個從句并不是拿來區(qū)分的概念,它們的使用場合很接近,并且適用范圍比較相似,才會拿出來對比。不知道你發(fā)現(xiàn)沒有,要想?yún)^(qū)分兩個比較近似的事物或者概念的話,多數(shù)時候它倆都是包含關(guān)系。因?yàn)閮蓚€概念只是相近,但是完全不沾邊的話,你也不可能分不開。
select-into
和 let
從句的適用范圍就是典型的包含關(guān)系。顯然,select-into
用得更少,因?yàn)樗倪m用范圍很小,而多數(shù)時候,let
從句都可以代替。甚至于前面的嵌套查詢寫法,我仍然可以用 let
從句來表述:
你看是吧。所以,select-into
和 let
的適用范圍實(shí)際上是一個包含關(guān)系:let
可以用在任何定義中間變量的時候;而 select-into
登場只用在代替嵌套查詢的時候。那么,你啥時候用 let
從句,啥時候用 select-into
從句,想必就不用多說了吧。
我推薦你這么做:
如果你要考慮優(yōu)化性能,而且還可以改寫為嵌套查詢的寫法,那么就用
select-into
從句;其它任何情況,全部一律無腦用
let
從句就完事了。
這個性能不性能的,我們以后講到 LINQ 的底層原理的時候會給大家說明。實(shí)際上
let
從句因?yàn)楦鼮閺V泛,所以它會被編譯器改寫為比較復(fù)雜的處理機(jī)制,以兼容所有的情況;但是select-into
使用情況更為具體,所以它比let
在性能上要更好。