接上文講,我們在上篇文章裡經常提到兩個東西(Linq系列:基礎與本質(Part I)),System.Linq.Enumerable和System.Func。那麼著 兩個東東到底是個什麼東西呢?我們看看下面的代碼:
LINQ表達式在編譯時,編譯器會將查詢操作符轉換為對 System.Linq.Enumerable 類型中若干函數的調用(或者其他類型)。下面是幾個 Enumerable 成員函數:
Code
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source,
System.Func<TSource,int,bool> predicate)
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source,
System.Func<TSource,bool> predicate)
public static int? Sum( this IEnumerable<int?> source );
我們可以看到這些函數大部分都需要代理作為參數,特別的是,定義在 System.Core.dll 中的 泛型代理 Func<>,其中很大一部分 是用到了c#3.X的新特性:Extension Method 。有興趣的朋友可以去看看。
我們來看看Func<>的定義:其中最後一個類型參數TResult代表返回類型:
Code
1 public delegate TResult Func<T0,T1,T2,T3,TResult>(
2 T0 arg0, T1 arg1, T2 arg2, T3 arg3)
3 public delegate TResult Func<T0,T1,T2,TResult>(T0 arg0, T1 arg1, T2 arg2)
4 public delegate TResult Func<T0,T1,TResult>(T0 arg0, T1 arg1)
5 public delegate TResult Func<T0,TResult>(T0 arg0)
6 public delegate TResult Func<TResult>()
由於 System.Linq.Enumerable 的很多成員函數需要代理作為參數,因此,在調用時,我們可以用下列方式實現:
一、使用查詢操作符定義查詢表達式
這是最直接和簡潔的方式,也是推薦方式,請參考上篇文章(Linq系列:基礎與本質(Part I))的例子代碼。
二、使用Enumerable類型函數和Lambda表達式定義查詢表達式
請參考上篇文章(Linq系列:基礎與本質(Part I))的例子代碼。
三、使用Enumerable類型函數和匿名方法定義查詢表達式
Code
1 Func<int, bool> searchFilter =delegate( int i )
2 {
3 return i < 10;
4 };
5 Func<int, int> item = delegate( int s )
6 {
7 return s;
8 };
9 var subset4 = numbers.Where( searchFilter )
10 .OrderBy( item ).Select( item );
可以看出這種方式比較繁瑣,因為我們自己定義了Where(), OrderBy(), and Select()等函數需要的Func<>代理。
四 使用Enumerable類型函數和代理定義查詢表達式
最繁瑣的方式就是,不使用Lambda表達式和匿名函數,為每個FUN<>類型手動定義代理。
Code
1 public static bool Filter( int s )
2 {
3 return s < 10;
4 }
5 public static int ProcessItem( int s )
6 {
7 return s;
8 }
但是變來變去都離不開委托和Enumerable類型提供的方法。
在這裡我們可以看到:
任何需要代理作為參數的函數,都可以改為用Lambda表達式作為參數。
Lambda表達式僅僅是匿名函數的掩飾,可以大大提高可讀性
匿名函數是手動定義代理類型並定義相應的處理函數的速記符號。
因此一些所謂的新技術其實就是建立在老技術上面的。。打好基礎才是最重要的。委托,匿名函數,Lambda其實是一脈相承的。請看Anytao 的《你必須知道的Net》。
最後希望大家對CLR系列和LINQ系列提出寶貴的建議以及希望增加對什麼知識點的講解。謝謝!
待續。。。