一、投影操作符
1. Select
Select操作符對單個序列或集合中的值進行投影。下面的示例中使用select從序列中返回Employee表的所有列:
using (NorthwindDataContext db=new NorthwindDataContext()) { //查詢語法 var query = from e in db.Employees where e.FirstName.StartsWith("M") select e; //方法語法 var q = db.Employees .Where(e => e.FirstName.StartsWith("M")) .Select(e => e);
foreach (var item in query) { Console.WriteLine(item.FirstName); } } |
當然,你也可以返回單個列,例如:
var query = from e in db.Employees where e.FirstName.StartsWith("M") select e.FirstName; |
你也可以返回序列中的某幾列,例如:
var query = from e in db.Employees where e.FirstName.StartsWith("M") select new { e.FirstName, e.LastName, e.Title }; |
2. SelectMany
SelectMany操作符提供了將多個from子句組合起來的功能,它將每個對象的結果合並成單個序列。下面是一個示例:
using (NorthwindDataContext db=new NorthwindDataContext()) { //查詢語法 var query = from e in db.Employees from o in e.Orders select o;
//方法語法 var q = db.Employees .SelectMany(e => e.Orders);
foreach (var item in query) { Console.WriteLine(item.Freight); } } |
二、限制操作符
Where是限制操作符,它將過濾標准應用在序列上,按照提供的邏輯對序列中的數據進行過濾。
Where操作符不啟動查詢的執行。當開始對序列進行遍歷時查詢才開始執行,此時過濾條件將被應用到查詢中。Where操作符的使用方法已經在第一節中出現過,這里不再冗述。
三、排序操作符
排序操作符,包括OrderBy、OrderByDescending、ThenBy、ThenByDescending和Reverse,提供了升序或者降序排序。
1. OrderBy
OrderBy操作符將序列中的元素按照升序排列。下面的示例演示了這一點:
using (NorthwindDataContext db = new NorthwindDataContext()) { //查詢語法 var query = from e in db.Employees orderby e.FirstName select e;
//方法語法 var q = db.Employees .OrderBy(e => e.FirstName) .Select(e => e);
foreach (var item in q) { Console.WriteLine(item.FirstName); } } |
這里可以使用OrderBy的重載方法OrderBy(Func<T,TKey>,IComparer<Tkey>)來指定序列的排序方式。
2. OrderByDescending
OrderByDescending操作符將序列中的元素按照降序排列。用法與OrderBy相同,這里不再演示。
3. ThenBy
ThenBy操作符實現按照次關鍵字對序列進行升序排列。此操作符的查詢語法與方法語法略有不同,以下代碼演示了這一點:
using (NorthwindDataContext db = new NorthwindDataContext()) { //查詢語法 var query = from e in db.Employees orderby e.FirstName,e.LastName select e;
//方法語法 var q = db.Employees .OrderBy(e => e.FirstName) .ThenBy(e => e.LastName) .Select(e => e);
foreach (var item in query) { Console.WriteLine(item.FirstName); } } |
4. ThenByDescending
ThenByDescending操作符實現按照次關鍵字對序列進行降序排列。此操作符的查詢語法與方法語法略有不同,以下代碼演示了這一點:
using (NorthwindDataContext db = new NorthwindDataContext()) { //查詢語法 var query = from e in db.Employees orderby e.FirstName,e.LastName descending select e;
//方法語法 var q = db.Employees .OrderBy(e => e.FirstName) .ThenByDescending(e => e.LastName) .Select(e => e);
foreach (var item in query) { Console.WriteLine(item.FirstName); } } |
5. Reverse
Reverse將會把序列中的元素按照從后到前的循序反轉。需要注意的是,Reverse方法的返回值是void,以下代碼演示了這一點:
using (NorthwindDataContext db = new NorthwindDataContext()) { //方法語法 var q = db.Employees .Select(e => e.FirstName) .ToList(); q.Reverse();
foreach (var item in q) { Console.WriteLine(item); } } |
四、聯接操作符
聯接是指將一個數據源對象與另一個數據源對象進行關聯或者聯合的操作。這兩個數據源對象通過一個共同的值或者屬性進行關聯。
LINQ有兩個聯接操作符:Join和GroupJoin。
1. Join
Join操作符類似於T-SQL中的inner join,它將兩個數據源相聯接,根據兩個數據源中相等的值進行匹配。例如,可以將產品表與產品類別表相聯接,得到產品名稱和與其相對應的類別名稱。以下的代碼演示了這一點:
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中 //查詢語法 var query = from p in db.Products join c in db.Categories on p.CategoryID equals c.CategoryID where p.CategoryID == 1 select p;
//方法語法 var q = db.Products .Join ( db.Categories, p => p.CategoryID, c => c.CategoryID, (p, c) => p ) .Where(p => p.CategoryID == 1);
foreach (var item in query) { Console.WriteLine(item.ProductName); } } |
以上代碼為表述清晰加入了一個條件“where p.CategoryID == 1”,即僅返回產品類別ID為1的所有產品。
2. GroupJoin
GroupJoin操作符常應用於返回“主鍵對象-外鍵對象集合”形式的查詢,例如“產品類別-此類別下的所有產品”。以下的代碼演示了這一點:
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中 //查詢語法 var query = from c in db.Categories join p in db.Products on c.CategoryID equals p.CategoryID into r select new { c.CategoryName, Products = r };
//方法語法 var q = db.Categories .GroupJoin ( db.Products, c => c.CategoryID, p => p.CategoryID, (c, p) => new { c.CategoryName, Products = p } );
foreach (var item in query) { Console.WriteLine("{0} =>", item.CategoryName); foreach (var p in item.Products) { Console.WriteLine(p.ProductName); } Console.WriteLine("----------------------------------------------"); } } |
五、分組操作符
分組是根據一個特定的值將序列中的元素進行分組。LINQ只包含一個分組操作符:GroupBy。
下面的示例中使用了產品表,以CategoryID作為分組關鍵值,按照產品類別對產品進行了分組。
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中 //查詢語法 var query = from p in db.Products group p by p.CategoryID;
//方法語法 var q = db.Products .GroupBy(p => p.CategoryID);
foreach (var item in query) { Console.WriteLine("{0} =>", item.Key); foreach (var p in item) { Console.WriteLine(p.ProductName); } Console.WriteLine("----------------------------------------------"); } } |
執行GroupBy得到的序列中包含的元素類型為IGrouping<TKey?, T>,其Key屬性代表了分組時使用的關鍵值,遍歷IGrouping<TKey?, T>元素可以讀取到每一個T類型。在此示例中,對應的元素類型為IGrouping<int?, Products>,其Key屬性即為類別ID,遍歷它可以讀取到每一個產品對象。
六、串聯操作符
串聯是一個將兩個集合聯接在一起的過程。在LINQ中,這個過程通過Concat操作符來實現。
在下面的示例中,將會把類別名稱串聯在產品名稱之后:
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中
//方法語法 var q = db.Products .Select(p => p.ProductName) .Concat ( db.Categories.Select(c => c.CategoryName) );
foreach (var item in q) { Console.WriteLine(item); } } |
七、聚合操作符
聚合函數將在序列上執行特定的計算,並返回單個值,如計算給定序列平均值、最大值等。共有7種LINQ聚合查詢操作符:Aggregate、Average、Count、LongCount、Max、Min和Sum。
1. Aggregate
Aggregate操作符對集合值執行自定義聚合運算。例如,需要列出所有產品類別清單,每個類別名稱之間用頓號連接。以下的代碼演示了這一過程:
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中
//方法語法 var q = db.Categories .Select(c => c.CategoryName) .ToArray() .Aggregate((current, next) => String.Format("{0}、{1}", current, next));
Console.WriteLine(q); } |
如果你對這一過程有些迷惑,那么請參照以下代碼:
var query = db.Categories .Select(c => c.CategoryName) .ToArray(); string r = String.Empty; foreach (var item in query) { r += "、"; r += item; } r = r.Substring(1); //去除第一個頓號 Console.WriteLine(r); |
2. Average
求集合中元素的平均值,返回值類型double
3. Count
求集合中元素的個數,返回值類型Int32
4. LongCount
求集合中元素的個數,返回值類型Int64
5. Max
求集合中元素的最大值
6. Min
求集合中元素的最小值
7. Sum
求集合中元素的和
八、集合操作符
LINQ 中的集合操作符是指根據相同或不同集合(或集)中是否存在等效元素來生成結果集的查詢操作,一共有4種:
方法名 |
說明 |
Distinct |
從集合移除重復值。 |
Except |
返回差集,差集是指位於一個集合但不位於另一個集合的元素。 |
Intersect |
返回交集,交集是指同時出現在兩個集合中的元素。 |
Union |
返回並集,並集是指位於兩個集合中任一集合的唯一的元素。 |
使用方式均為“集合1.方法名(集合2)”,返回值為運算結果的集合,這里就不演示了。
九、生成操作符
生成是指創建新的值序列。
1. Empty
Empty操作符返回一個指定類型的空集合。這里的空不是null,而是元素數量為0的集合。以下的示例演示了如何創建一個IEnumerable<int>類型的空集合:
var q = Enumerable.Empty<int>(); Console.WriteLine(q == null); Console.WriteLine(q.Count()); |
2. DefaultIfEmpty
DefaultIfEmpty將空集合替換為具有默認值的單一實例集合。執行此方法獲得的集合將至少含有一個元素,這是因為DefaultIfEmpty方法需要兩個參數,第一個參數是一個泛型集合,第二個參數是相應類型的單個元素,如果第一個參數中不含有任何元素,它將返回第二個參數指定的單個元素。如果你使用了DefaultIfEmpty方法的重載方法DefaultIfEmpty<T>(IEnumerable<T> array),如果指定的array集合為空,那么將返回一個類型為T,值為null的單個對象。以下的代碼演示了這一過程:
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中
//方法語法 var q = Enumerable.DefaultIfEmpty ( db.Employees .Where(e => e.FirstName.StartsWith("Aaf")) //更改此處的條件可獲得不同的集合 , new Employees() { FirstName = "Sunny D.D" } ); Console.WriteLine(q.Count()); foreach (var item in q) { Console.WriteLine(item.FirstName); } } |
3. Range
Range操作符用於生成指定范圍內的整數的序列。它需要兩個參數,第一個參數是序列開始的整數值,第二個參數是序列中整數的數量。下面的示例演示了使用Range操作符來生成從0到9的整數序列:
var q = Enumerable.Range(0, 10); foreach (var item in q) { Console.WriteLine(item); } |
4. Repeat
Repeat操作符用於生成包含一個重復值的集合。它需要兩個參數,第一個參數是任意類型的元素,第二個參數是生成的序列中所包含此元素的數量。下面的示例演示了使用Repeat來生成一個包含10個0的序列:
var q = Enumerable.Repeat(0, 10); foreach (var item in q) { Console.WriteLine(item); } |
十、轉換操作符
轉換操作符是用來實現將輸入對象的類型轉變為序列的功能。名稱以“As”開頭的轉換方法可更改源集合的靜態類型但不枚舉(延遲加載)此源集合。名稱以“To”開頭的方法可枚舉(即時加載)源集合並將項放入相應的集合類型。
1. AsEnumerable
所有實現了IEnumerable<T>接口的類型都可以調用此方法來獲取一個IEnumerable<T>集合。此方法一般僅用於實現類中的方法與IEnumerable<T>接口方法重名時。例如,實現類Test中有一個Where方法,當使用Test對象調用Where時,將執行Test自身的Where方法過程。如果要執行IEnumerable<T>的Where方法,便可以使用AsEnumerable進行進行轉換后,再調用Where方法即可。當然,將實現類Test隱式轉換為IEnumerable<T>接口,再調用接口的Where方法也能達到同樣的效果。以下的代碼演示了這一過程:
class AsEnumerableTest<T> : List<T> { public void Where(Func<T, bool> func) { Console.WriteLine("AsEnumerableTest的Where方法"); } } public static void AsEnumerable() { AsEnumerableTest<int> q = new AsEnumerableTest<int>() { 1,2,3,4 }; q.Where(r => r < 3);
//q.AsEnumerable().Where(r => r < 3);
//IEnumerable<int> i = q; //i.Where(r => r < 3); } |
2. Cast
Cast<T> 方法通過提供必要的類型信息,可在IEnumerable(非泛型)的派生對象上調用Cast<T> 方法來獲得一個IEnumerable<T>對象。例如,ArrayList 並不實現IEnumerable<T>,但通過調用 ArrayList 對象上的 Cast<T>(),就可以使用標准查詢運算符查詢該序列。
如果集合中的元素無法強制轉換為 T 類型,則此方法將引發異常。以下代碼演示了這一過程:
ArrayList array = new ArrayList(); array.Add("Bob"); array.Add("Jack"); array.Add(1); foreach (var item in array.Cast<string>()) { Console.WriteLine(item); } |
運行此代碼,可以輸出“Bob”、“Jack”,然后會報出一個異常“無法將int強制轉換為string”,這說明Cast方法也是延遲執行實現的,只有在枚舉過程中才將對象逐個強制轉換為T類型。
3. OfType
OfType <T> 方法通過提供必要的類型信息,可在IEnumerable(非泛型)的派生對象上調用OfType <T> 方法來獲得一個IEnumerable<T>對象。執行OfType<T>方法將返回集合中強制轉換類型成功的所有元素。也就是說,OfType<T>方法與Cast<T> 方法的區別在於,如果集合中的元素在強制轉換失敗的時候會跳過,而不是拋出異常。
4. ToArray
ToArray 操作符可以在IEnumerable<T> 類型的任何派生對象上調用,返回值為T類型的數組。
5. ToDictionary
ToDictionary操作符根據指定的鍵選擇器函數,從IEnumerable<T>創建一個Dictionary<TKey, TValue>。下面的示例中,將查詢到的產品類別集合轉換為Dictionary<類別ID,類別名稱>的鍵-值集合:
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中 //方法語法 var q = db.Categories .ToDictionary ( c => c.CategoryID, c => c.CategoryName );
foreach (var item in q) { Console.WriteLine("{0} - {1}",item.Key,item.Value); } } |
需要注意的是,如果省略ToDictionary方法的第二個參數(值選擇函數),那么Value將會保存一個類別對象。還有,如果Key為null,或者出現重復的Key,都將導致拋出異常。
6. ToList
ToList操作符可以在IEnumerable<T> 類型的任何派生對象上調用,返回值為List<T>類型的對象。
7. ToLookup
ToLookup操作符將創建一個 Lookup<TKey, TElement>對象,這是一個one-to-many集合,一個Key可以對應多個Value。以下的示例以產品表的所有數據作為數據源,以類別ID作為Key調用了ToLookup方法,然后遍歷返回的Lookup<TKey, TElement>對象,輸出了類別ID以及此類別下的所有產品名稱:
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中 //方法語法 var q = db.Products .ToLookup ( p => p.CategoryID, p => p.ProductName );
foreach (var item in q) { Console.WriteLine(item.Key); foreach (var p in item) { Console.WriteLine(p); } } } |
可以看出,ToLookup操作與GroupBy操作很相似,只不過GroupBy是延遲加載的,而ToLookup是即使加載。
十一、元素操作符
元素操作符將從一個序列中返回單個指定的元素。
1. First
First操作將返回序列中的第一個元素。如果序列中不包含任何元素,則First<T>方法將引發異常。若要在源序列為空時返回默認值,需要使用FirstOrDefault方法。以下代碼演示了First<T>方法的使用方式:
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中 //無參 var query = db.Employees .First();
//有參 var q = db.Employees .First(e => e.FirstName.StartsWith("S"));
Console.WriteLine(q.FirstName); } |
上述代碼中使用了First<T>方法的無參方式與有參方式。First<T>的有參方式中可以指定一個條件,操作將返回序列中滿足此條件的第一個元素。從查詢結果上看,source.First<T>(條件)方法與source.Where(條件).First<T>()是一樣的,但是需要注意“First<T>(條件)操作將返回序列中滿足此條件的第一個元素”,這將忽略后面的遍歷操作,效率更高。
2. FirstOrDefault
FirstOrDefault方法將返回序列中的第一個元素;如果序列中不包含任何元素,則返回默認值。它也可以像First方法一樣傳遞一個條件。需要說明的是如果序列中不包含任何元素,返回的默認值是個怎樣的元素。在這之前,先來看一下FirstOrDefault方法是如何實現的:
public static TSource FirstOrDefault<TSource>(this IEnumerable<TSource> source) { if (source == null) { throw Error.ArgumentNull("source"); } IList<TSource> list = source as IList<TSource>; if (list != null) { if (list.Count > 0) { return list[0]; } } else { using (IEnumerator<TSource> enumerator = source.GetEnumerator()) { if (enumerator.MoveNext()) { return enumerator.Current; } } } return default(TSource); } |
- 如果調用FirstOrDefault方法的序列為空,拋出異常
- 如果序列成功轉換為List<T>,並且元素數量大於0,則返回首個元素
- 如果序列沒有成功轉換為List<T>,則嘗試獲取序列的遍歷器,然后再調用遍歷器的MoveNext方法,如果返回值為true,則返回當前的元素。
- 如果上述操作都沒有執行,則使用default(T)關鍵字返回類型T的默認值
以下給出MSDN中,對於default(T)關鍵字的描述:
在泛型類和泛型方法中產生的一個問題是,在預先未知以下情況時,如何將默認值分配給參數化類型 T:
給定參數化類型 T 的一個變量 t,只有當 T 為引用類型時,語句 t = null 才有效;只有當 T 為數值類型而不是結構時,語句 t = 0 才能正常使用。解決方案是使用 default 關鍵字,此關鍵字對於引用類型會返回 null,對於數值類型會返回零。對於結構,此關鍵字將返回初始化為零或 null 的每個結構成員,具體取決於這些結構是值類型還是引用類型。 |
3. Last
Last方法將返回序列中的最后一個元素。使用方法參照First。
4. LastOrDefault
LastOrDefault方法將返回序列中的最后一個元素;如果序列中不包含任何元素,則返回默認值。使用方法參照FirstOrDefault。
5. ElementAt
ElementAt方法返回序列中指定索引處的元素。使用方法參照First。需要注意的是如果索引超出范圍會導致異常。
6. ElementAtOrDefault
ElementAtOrDefault方法將返回序列中指定索引處的元素;如果索引超出范圍,則返回默認值。使用方法參照FirstOrDefault。
7. Single
Single方法的無參形式將從一個序列中返回單個元素,如果該序列包含多個元素,或者沒有元素數為0,則會引發異常。也就是說,在序列執行Single方法的無參形式時,必須保證該序列有且僅有一個元素。
Single方法的有參形式將從一個序列中返回符合指定條件的唯一元素,如果有多個元素,或者沒有元素符合這一條件,則會引發異常。以下代碼演示了Single的使用方式:
using (NorthwindDataContext db = new NorthwindDataContext()) { db.Log = Console.Out; //將生成的T-SQL語句輸出到控制台中 //方法語法 var q = db.Employees .Single();
var query = db.Employees .Single(e => e.FirstName.StartsWith("S")); Console.WriteLine(query.FirstName); } |
8. SingleOrDefault
SingleOrDefault方法的無參形式將從一個序列中返回單個元素。如果元素數為0,則返回默認值。如果該序列包含多個元素,則會引發異常。
SingleOrDefault方法的有參形式將從一個序列中返回符合指定條件的唯一元素,如果元素數為0,則返回默認值;如果該序列包含多個元素,則會引發異常。SingleOrDefault的使用方式與Single相同。
需要注意的是,Single方法與SingleOrDefault方法都是即時加載的,在代碼進行到方法所在位置時,如果引發了異常,會立刻拋出。
十二、相等操作符
如果兩個序列的對應元素相等且這兩個序列具有相同數量的元素,則視這兩個序列相等。
SequenceEqual方法通過並行地枚舉兩個數據源並比較相應元素來判斷兩個序列是否相等。如果兩個序列完全相等,返回true,否則返回false。以下代碼是SequenceEqual方法的實現過程:
public static bool SequenceEqual<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second,IEqualityComparer<TSource> comparer) { if (comparer == null) { comparer = EqualityComparer<TSource>.Default; } if (first == null) { throw Error.ArgumentNull("first"); } if (second == null) { throw Error.ArgumentNull("second"); } using (IEnumerator<TSource> enumerator = first.GetEnumerator()) { using (IEnumerator<TSource> enumerator2 = second.GetEnumerator()) { while (enumerator.MoveNext()) { if (!enumerator2.MoveNext() || !comparer.Equals(enumerator.Current, enumerator2.Current)) { return false; } } if (enumerator2.MoveNext()) { return false; } } } return true; } |
以上代碼的執行過程為:
- 如果比較器為null,賦值為默認值EqualityComparer<TSource>.Default。
- 如果序列1為null,拋出異常。
- 如果序列2為null,拋出異常。
- 遍歷序列1。在此過程中,如果序列2到達底端則返回false;如果序列1的當前值與序列2的當前值不同,則返回false。
- 序列1遍歷完成后,如果序列2未到達底端,則返回false。
- 如果第2-5步都沒有執行,則返回true。
十三、限定操作符
限定符運算返回一個 Boolean 值,該值指示序列中是否有一些元素滿足條件或是否所有元素都滿足條件。
下圖描述了兩個不同源序列上的兩個不同限定符運算。第一個運算詢問是否有一個或多個元素為字符“A”,結果為 true。第二個運算詢問是否所有元素都為字符“A”,結果為true。
1. All
All方法用來確定是否序列中的所有元素都滿足條件。以下代碼演示了All的用法:
string[] source1 = new string[] { "A", "B", "C", "D", "E", "F" }; string[] source2 = new string[] { "A", "A", "A", "A", "A", "A" };
Console.WriteLine(source1.All(w => w == "A")); //console will print "False" Console.WriteLine(source2.All(w => w == "A")); //console will print "True" |
2. Any
Any方法的無參方式用來確定序列是否包含任何元素。如果源序列包含元素,則為 true;否則為 false。
Any方法的有參方式用來確定序列中是否有元素滿足條件。只要有一個元素符合指定條件即返回true,如果一個符合指定條件的元素都沒有則返回false。以下代碼演示了Any方法有參方式的用法:
string[] source1 = new string[] { "A", "B", "C", "D", "E", "F" }; string[] source2 = new string[] { "A", "A", "A", "A", "A", "A" };
Console.WriteLine(source1.Any(w => w == "A")); //console will print "True" Console.WriteLine(source2.Any(w => w == "A")); //console will print "True" |
3. Contains
Contains方法用來確定序列是否包含滿足指定條件的元素。如果有返回true,否則返回false。以下代碼使用默認的String比較器來判斷序列中是否含有指定的字符串:
string[] source1 = new string[] { "A", "B", "C", "D", "E", "F" };
Console.WriteLine(source1.Contains("A")); //console will print "True" Console.WriteLine(source1.Contains("G")); //console will print "False" |
如果要對序列中的元素進行自定義比較,需要一個IEqualityComparer<T>接口的實現類作為比較器,用於比較序列中的元素。
十四、分區操作符
LINQ 中的分區指的是在不重新排列元素的情況下,將輸入序列划分為兩部分,然后返回其中一個部分的操作。
下圖顯示對一個字符序列執行三個不同的分區操作的結果。第一個操作返回序列中的前三個元素。第二個操作跳過前三個元素,返回剩余的元素。第三個操作跳過序列中的前兩個元素,返回接下來的三個元素。
1. Take
Take(int n)方法將從序列的開頭返回數量為n的連續元素。以下代碼演示了從一個序列中返回其前五個元素:
int[] source = new int[] { 86, 2, 77, 94, 100, 65, 5, 22, 70, 55, 81, 66, 45 }; var q = source.Take(5); foreach (var item in q) { Console.WriteLine(item); } |
上述代碼的運行結果為下圖所示:
2. TakeWhile
TakeWhile方法執行時將逐個比較序列中的每個元素是否滿足指定條件,直到碰到不符合指定的條件的元素時,返回前面所有的元素組成的序列。以下代碼演示了這一過程:
int[] source = new int[] { 86, 2, 77, 94, 100, 65, 5, 22, 70, 55, 81, 66, 45 }; var q = source.TakeWhile(i => i < 100); foreach (var item in q) { Console.WriteLine(item); } |
上述代碼的運行結果為下圖所示:
3. Skip
Skip(int n)方法將跳過序列開頭的n個元素,然后返回其余的連續元素。以下代碼演示了從一個序列中跳過前五個元素,然后返回其余的元素組成的序列:
int[] source = new int[] { 86, 2, 77, 94, 100, 65, 5, 22, 70, 55, 81, 66, 45 }; var q = source.Skip(5); foreach (var item in q) { Console.WriteLine(item); } |
上述代碼的運行結果為下圖所示:
4. SkipWhile
SkipWhile方法執行時將逐個比較序列中的每個元素是否滿足指定條件,直到碰到不符合指定的條件的元素時,返回其余所有的元素組成的序列。以下代碼演示了這一過程:
int[] source = new int[] { 86, 2, 77, 94, 100, 65, 5, 22, 70, 55, 81, 66, 45 }; var q = source.SkipWhile(i => i < 100); foreach (var item in q) { Console.WriteLine(item); } |
上述代碼的運行結果為下圖所示:
本文總結
本文介紹了LINQ標准查詢操作符。沒有這些操作符,LINQ就不會存在。本文為理解這些操作符的功能提供了很好的基礎。了解它們將會很有幫助,因為LINQ的各種Provider都是基於這些操作符來完成各自豐富的功能。