【More Effective C#】LINQ表达式与方法调用的映射
LINQ構(gòu)建在兩個(gè)概念之上,一種查詢(xún)語(yǔ)言和一系列將查詢(xún)語(yǔ)言轉(zhuǎn)換成方法調(diào)用的實(shí)現(xiàn).在編譯時(shí),編譯器將LINQ表達(dá)式(LINQ?to?object)轉(zhuǎn)換成方法調(diào)用.
.Net基礎(chǔ)類(lèi)庫(kù)提供了兩種擴(kuò)展方法.System.Linq.Enumerable使用了IEnumerable<T>上擴(kuò)展來(lái)實(shí)現(xiàn),而System.Linq.Queryable則提供了類(lèi)似的一系列IQueryable<T>上的擴(kuò)展.兩者的轉(zhuǎn)換略為不同.前者在編譯時(shí)轉(zhuǎn)換成相應(yīng)的擴(kuò)展方法調(diào)用.而后者則能將LINQ表達(dá)式轉(zhuǎn)換成SQL查詢(xún),并有SQL數(shù)據(jù)庫(kù)引擎執(zhí)行.
從LINQ表達(dá)式到方法調(diào)用的轉(zhuǎn)換時(shí)一個(gè)復(fù)雜的迭代過(guò)程.編譯器在轉(zhuǎn)換時(shí)也有一個(gè)特定的順序.
例如
?int[]?someNumbers?=?{?0,?1,?2,?3,?4,?5,?6,?7,?8,?9?};
????????????var?answer?=?from?n?in?someNumbers
?????????????????????????where?n?<?5
?????????????????????????select?n;
最后將轉(zhuǎn)換成
int[]?someNumbers?=?{?0,?1,?2,?3,?4,?5,?6,?7,?8,?9?};
????????????var?answer?=someNumbers.Where(n=>n<5);
可以看到.在上面的轉(zhuǎn)換后.Select被優(yōu)化去掉了.這就是一個(gè)退化選擇.不止是Where和Select.相應(yīng)的LINQ表達(dá)式都會(huì)被轉(zhuǎn)換成相應(yīng)的擴(kuò)展方法..
編譯器的轉(zhuǎn)換
C#編譯器將把查詢(xún)和lambda表達(dá)式(Linq?to?object)轉(zhuǎn)換成靜態(tài)委托,實(shí)力委托和閉包.
int[]?someNumbers?=?{?0,?1,?2,?3,?4,?5,?6,?7,?8,?9?};
????????????var?answer?=?from?n?in?someNumbers
?????????????????????????select?n;
把上邊的代碼編譯.使用Refletor打開(kāi)程序集.查看生成的相關(guān)代碼.
?int[]?someNumbers?=?new?int[]?{?0,?1,?2,?3,?4,?5,?6,?7,?8,?9?};
????if?(CS$<>9__CachedAnonymousMethodDelegate1?==?null)
????{
????????CS$<>9__CachedAnonymousMethodDelegate1?=?new?Func<int,?int>(null,?(IntPtr)?<Main>b__0);
????}
????IEnumerable<int>?answer?=?Enumerable.Select<int,?int>(someNumbers,?CS$<>9__CachedAnonymousMethodDelegate1);
可以看到.編譯器自動(dòng)生成了一個(gè)委托.下面.使用更為直觀的代碼描述.生成的代碼大致如下:
?private?static?int?HiddenFuc(int?n)
????????{
????????????return?n?*?n;
????????}
????????private?static?Func<int,?int>?HiddenDelegateDefinition
?int[]?someNumbers?=?new?int[]?{?0,?1,?2,?3,?4,?5,?6,?7,?8,?9?};
????????????if?(HiddenDelegateDefinition?==?null)
????????????{
????????????????HiddenDelegateDefinition?=?new?Func<int,?int>(HiddenFuc);
????????????}
????????????IEnumerable<int>?anser?=?someNumbers.Select<int,?int>(HiddenDelegateDefinition);
可以看到.編譯器生成了一個(gè)靜態(tài)方法實(shí)現(xiàn)Select表達(dá)式.并且通過(guò)委托實(shí)現(xiàn)查詢(xún).
實(shí)際上.上述的lambda表達(dá)式的主體部分并沒(méi)有訪問(wèn)任何實(shí)例變量或是局部變量.什么是實(shí)例變量.什么又是局部變量.?
訪問(wèn)實(shí)例變量的Lambe表達(dá)式
public?class?ModFilter
????{
????????private?readonly?int?modulus;
????????public?ModFilter(int?mod)
????????{
????????????modulus?=?mod;
????????}
????????public?IEnumerable<int>?FindValues(IEnumerable<int>?sequence)
????????{
????????????return?from?n?in?sequence
???????????????????where?n?%?modulus?==?0???//訪¤問(wèn)實(shí)例變量
???????????????????select?n?*?n;
????????}
????}
編譯器將會(huì)為你生成一個(gè)實(shí)例方法,生成的代碼大致如下
?public?class?ModFilter
????{
????????private?readonly?int?modulus;
????????public?ModFilter(int?mod)
????????{
????????????modulus?=?mod;
????????}
????????private?bool?WhereClause(int?n)
????????{
????????????return?(n?%?modulus)?==?0;
????????}
????????private?static?int?SelectClause(int?n)
????????{
????????????return?n?*?n;
????????}
????????private?static?Func<int,?int>?SelectDelegate;
????????public?IEnumerable<int>?FindValues(IEnumerable<int>?sequence)
????????{
????????????if?(SelectDelegate?==?null)
????????????{
????????????????SelectDelegate?=?new?Func<int,?int>(SelectClause);
????????????}
????????????return?sequence.Where<int>(new?Func<int,?bool>(this.WhereClause)).Select<int,?int>(SelectClause);
????????}
}
Lambda表達(dá)式訪問(wèn)實(shí)例變量
? 若是Lambda表達(dá)式中訪問(wèn)了外部方法的實(shí)例變量.則編譯器將自動(dòng)生成一個(gè)私有的嵌套類(lèi)型.
public?class?ModFilterCloser
????{
????????private?readonly?int?modulus;
????????public?ModFilterCloser(int?mod)
????????{
????????????modulus?=?mod;
????????}
????????public?IEnumerable<int>?FindValues(IEnumerable<int>?sequence)
????????{
????????????int?numValues?=?0;
????????????return?from?n?in?sequence
???????????????????where?n?%?modulus?==?0
???????????????????select?n?*?n?/?++numValues;?//調(diào)用了方法外的局部變量numValues
????????}
????}
生成的代碼大致如下.
?public?class?ModFilterCloser
????{
????????private?sealed?class?Closure
????????{
????????????public?ModFilterCloser?outer;
????????????public?int?numValues;
????????????public?int?SelectClause(int?n)
????????????{
????????????????return?(n?*?n)?/?++this.numValues;
????????????}
????????}
????????private?readonly?int?modulus;
????????public?ModFilterCloser(int?mod)
????????{
????????????modulus?=?mod;
????????}
????????private?bool?WhereClause(int?n)
????????{
????????????return?(n?%?modulus)?==?0;
????????}
????????public?IEnumerable<int>?FindValues(IEnumerable<int>?sequence)
????????{
????????????Closure?c?=?new?Closure();
????????????c.outer?=?this;
????????????c.numValues?=?0;
????????????return?sequence.Where<int>(new?Func<int,bool>(this.WhereClause)).Select<int,int>(c.SelectClause));
????????}
????}
LINQ?to?Sql?的實(shí)現(xiàn)
最后.要注意到.以上的轉(zhuǎn)換實(shí)現(xiàn)都是在Linq?to?object中實(shí)現(xiàn).即IEnumberale<T>中.而LINQ?to?SQL?的轉(zhuǎn)換.編譯后可以看到.并沒(méi)發(fā)生任何變化.那是因?yàn)?/font>.只有在遍歷迭代時(shí),延遲執(zhí)行.LINQ?to?SQL?Provider才將LINQ表達(dá)式轉(zhuǎn)換成SQL查詢(xún).
轉(zhuǎn)載于:https://www.cnblogs.com/kongyiyun/archive/2010/10/15/1851866.html
總結(jié)
以上是生活随笔為你收集整理的【More Effective C#】LINQ表达式与方法调用的映射的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: JavaScript:prototype
- 下一篇: c# char unsigned_dll