原文章 : http://www.cnblogs.com/liulun/archive/2013/02/26/2909985.htmlhtml
1、11個與LINQ有關的語言特性:
【隱式類型、匿名類型、對象初始化器】、【自動屬性】、【委託、泛型、泛型委託】、【匿名方法、Lambda表達式——匿名方法的簡化寫法】、【擴展方法——對接口也生效、迭代器】 1. 隱式類型 var num = 1; 2. 匿名類型 var obj = new {id=1,name="aa"}; 3. 對象初始化器 var myObj = new MyObj(){id=1, name="aa"}; ---------------------------------------------------------------- 4. 自動屬性 public string Title {get; set;} ---------------------------------------------------------------- 5. 委託:委託是一種類型 delegate bool MoreOrLessDelgate(int item); 委託類型,和類是一個級別的,它定義了某種方法規範。 委託對象,和對象是同級別的,它指向某個方法。 委託對象在使用時,實際上調用的是它指向的方法。 6. 泛型:避免裝箱拆箱操做時的類型轉化的性能損耗。 預約義的泛型類型 List<T> Dictionary<TKey, TValue> 自定義泛型類型 public class SomeFac<T> { public T(); public static T Instance() { return default(T); } } 自定義泛型類型時的泛型約束 public class SomeFac<T> where T: myObj public class SomeFac<T> where T: myObj, new() //必須有一個構造函數 7. 泛型委託 預約義的三種泛型委託 public delegate bool Predicate<in T>(T obj);//傳入一個T類型的參數,返回bool類型的值 public delegate void Action<in T1...T16>(T1 obj1, ..16)//傳入0個到16個參數,無返回值 public delegate TResult Func<in T1...T16, TResult>(T1 obj1, ..16)//傳入0個到16個參數,返回一個T類型值 ---------------------------------------------------------------- 8. 匿名方法:delegate (int item){方法體}; var print = new Action<int>(delegate(int a){Console.WriteLine(a);}); 其中,匿名方法代碼以下: delegate(int a){Console.WriteLine(a);} 9. Lambda表達式:匿名方法的簡化寫法 delegate(int a){Console.WriteLine(a);} 更改成: a=>Console.WriteLine(a);//a的類型由編譯器自動推斷 var print = new Action<int>(delegate(int a){Console.WriteLine(a);}); 簡寫爲: var print = new Action<int>(a=>Console.WriteLine(a)); =>是lambda操做符 Console.WriteLine(a)是要執行的語句。 若是是多條語句的話,能夠用{}包起來。 若是須要返回值的話,能夠直接寫return語句 ---------------------------------------------------------------- 10. 擴展方法 想給一個類型增長行爲,一般是經過繼承的方式實現。 新的方式是使用擴展方法。 public static void PrintString(this String val) { Console.WriteLinie(val); } 以後,則能夠這樣調用。 var a = "aaa; a.PrintString(); 原本string類型沒有PrintString方法。 但經過咱們上面的代碼,就給string類型"擴展"了一個PrintString方法 (1)先決條件 <1>擴展方法必須在一個非嵌套、非泛型的靜態類中定義 <2>擴展方法必須是一個靜態方法 <3>擴展方法至少要有一個參數【這個參數的類型就是增長行爲的類型】 <4>第一個參數必須附加this關鍵字做爲前綴 <5>第一個參數不能有其餘修飾符(好比ref或者out) <6>第一個參數不能是指針類型 (2)注意事項 <1>跟前面提到的幾個特性同樣,擴展方法只會增長編譯器的工做,不會影響性能(用繼承的方式爲一個類型增長特性反而會影響性能) <2>若是原來的類中有一個方法,跟你的擴展方法同樣(至少用起來是同樣),那麼你的擴展方法獎不會被調用,編譯器也不會提示你 <3>擴展方法太強大了,會影響架構、模式、可讀性等等等等.... 11. 迭代器 每次針對集合類型編寫foreach代碼塊,都是在使用迭代器 這些集合類型都實現了IEnumerable接口,都有一個GetEnumerator方法。 static IEnumerable<int> GetIterator() { Console.WriteLine("迭代器返回了1"); yield return 1; Console.WriteLine("迭代器返回了2"); yield return 2; Console.WriteLine("迭代器返回了3"); yield return 3; } yield 關鍵字,在迭代器塊中用於向枚舉數對象提供值或發出迭代結束信號。 注意事項 <1>作foreach循環時多考慮線程安全性 在foreach時不要試圖對被遍歷的集合進行remove和add等操做 任何集合,即便被標記爲線程安全的,在foreach的時候,增長項和移除項的操做都會致使異常 (我在這裏犯過錯) <2>IEnumerable接口是LINQ特性的核心接口 只有實現了IEnumerable接口的集合 才能執行相關的LINQ操做,好比select,where等 這些操做,咱們接下來會講到。 ----------------------------------------------------------------
2、Linq
【查詢操做符、查詢表達式】 1. 查詢操做符 (1)源起 .net的設計者在類庫中定義了一系列的擴展方法 來方便用戶操做集合對象 這些擴展方法構成了LINQ的查詢操做符 (2)使用 這一系列的擴展方法,好比: Where,Max,Select,Sum,Any,Average,All,Concat等 都是針對IEnumerable的對象進行擴展的 也就是說,只要實現了IEnumerable接口,就可使用這些擴展方法 List<int> arr = new List<int>() { 1, 2, 3, 4, 5, 6, 7 }; var result = arr.Where(a => { return a > 3; }).Sum(); Where擴展方法,須要傳入一個Func<int,bool>類型的泛型委託 這個泛型委託,須要一個int類型的輸入參數和一個布爾類型的返回值 咱們直接把a => { return a > 3; }這個lambda表達式傳遞給了Where方法 a就是int類型的輸入參數,返回a是否大於3的結果 Sum擴展方法計算了Where擴展方法返回的集合的和。 (3)好處 arr.Where(a => { return a > 3; }).Sum(); 等同於 (from v in arr where v > 3 select v).Sum(); (4)標準查詢操做符說明 <1>過濾 Where 用法:arr.Where(a => { return a > 3; }) 說明:找到集合中知足指定條件的元素 OfType 用法:arr.OfType<int>() 說明:根據指定類型,篩選集合中的元素 <2>投影 Select 用法:arr.Select<int, string>(a => a.ToString()); 說明:將集合中的每一個元素投影的新集合中。上例中:新集合是一個IEnumerable<String>的集合 SelectMany 用法:arr.SelectMany<int, string>(a => { return new List<string>() { "a", a.ToString() }; }); 說明:將序列的每一個元素投影到一個序列中,最終把全部的序列合併 <3>還有不少查詢操做符,請翻MSDN,之後有時間我將另起一篇文章把這些操做符寫全。 2. 查詢表達式 (1)源起 上面咱們已經提到,使用查詢操做符表示的擴展方法來操做集合 雖然已經很方便了,但在可讀性和代碼的語義來考慮,仍有不足 因而就產生了查詢表達式的寫法。 雖然這很像SQL語句,但他們卻有着本質的不一樣。 (2)用法 from v in arr where v > 3 select v 這就是一個很是簡單的查詢表達式