日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

【More Effective C#】LINQ表达式与方法调用的映射

發布時間:2024/8/22 46 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【More Effective C#】LINQ表达式与方法调用的映射 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LINQ構建在兩個概念之上,一種查詢語言和一系列將查詢語言轉換成方法調用的實現.在編譯時,編譯器將LINQ表達式(LINQ?to?object)轉換成方法調用.

.Net基礎類庫提供了兩種擴展方法.System.Linq.Enumerable使用了IEnumerable<T>上擴展來實現,System.Linq.Queryable則提供了類似的一系列IQueryable<T>上的擴展.兩者的轉換略為不同.前者在編譯時轉換成相應的擴展方法調用.而后者則能將LINQ表達式轉換成SQL查詢,并有SQL數據庫引擎執行.

LINQ表達式到方法調用的轉換時一個復雜的迭代過程.編譯器在轉換時也有一個特定的順序.

例如

?int[]?someNumbers?=?{?0,?1,?2,?3,?4,?5,?6,?7,?8,?9?};

????????????var?answer?=?from?n?in?someNumbers

?????????????????????????where?n?<?5

?????????????????????????select?n;

最后將轉換成

int[]?someNumbers?=?{?0,?1,?2,?3,?4,?5,?6,?7,?8,?9?};

????????????var?answer?=someNumbers.Where(n=>n<5);

可以看到.在上面的轉換后.Select被優化去掉了.這就是一個退化選擇.不止是Where和Select.相應的LINQ表達式都會被轉換成相應的擴展方法..

編譯器的轉換

C#編譯器將把查詢和lambda表達式(Linq?to?object)轉換成靜態委托,實力委托和閉包.

int[]?someNumbers?=?{?0,?1,?2,?3,?4,?5,?6,?7,?8,?9?};

????????????var?answer?=?from?n?in?someNumbers

?????????????????????????select?n;

把上邊的代碼編譯.使用Refletor打開程序集.查看生成的相關代碼.

?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);

可以看到.編譯器自動生成了一個委托.下面.使用更為直觀的代碼描述.生成的代碼大致如下:

?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);

可以看到.編譯器生成了一個靜態方法實現Select表達式.并且通過委托實現查詢.

實際上.上述的lambda表達式的主體部分并沒有訪問任何實例變量或是局部變量.什么是實例變量.什么又是局部變量.?

訪問實例變量的Lambe表達式

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???//訪¤問實例變量

???????????????????select?n?*?n;

????????}

????}

編譯器將會為你生成一個實例方法,生成的代碼大致如下

?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表達式訪問實例變量

? 若是Lambda表達式中訪問了外部方法的實例變量.則編譯器將自動生成一個私有的嵌套類型.

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;?//調用了方法外的局部變量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?的實現

最后.要注意到.以上的轉換實現都是在Linq?to?object中實現.IEnumberale<T>.LINQ?to?SQL?的轉換.編譯后可以看到.并沒發生任何變化.那是因為.只有在遍歷迭代時,延遲執行.LINQ?to?SQL?Provider才將LINQ表達式轉換成SQL查詢.

轉載于:https://www.cnblogs.com/kongyiyun/archive/2010/10/15/1851866.html

總結

以上是生活随笔為你收集整理的【More Effective C#】LINQ表达式与方法调用的映射的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。