日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

LINQ标准查询操作符

發布時間:2025/4/14 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LINQ标准查询操作符 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本文基于.NET Framework 2.0編寫

本文PDF下載

推薦大家下載本文的PDF進行閱讀,可以方便的使用書簽來閱讀各個方法,而且代碼中的關鍵字是高亮顯示的。

轉載請注明出處。

一、投影操作符

1. Select

Select操作符對單個序列或集合中的值進行投影。下面的示例中使用select從序列中返回Employee表的所有列:

using (NorthwindDataContext db=new NorthwindDataContext())<?xml:namespace prefix = o />

{

??? //查詢語法

??? 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操作符的使用方法已經在第一節中出現過,這里不再冗述。

三、排序操作符

排序操作符,包括OrderByOrderByDescendingThenByThenByDescendingReverse,提供了升序或者降序排序。

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有兩個聯接操作符:JoinGroupJoin

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”,即僅返回產品類別ID1的所有產品。

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

??? }

}

七、聚合操作符

聚合函數將在序列上執行特定的計算,并返回單個值,如計算給定序列平均值、最大值等。共有7LINQ聚合查詢操作符:AggregateAverageCountLongCountMaxMinSum

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操作符來生成從09的整數序列:

var q =

??? Enumerable.Range(0, 10);

foreach (var item in q)

{

??? Console.WriteLine(item);

}

4. Repeat

Repeat操作符用于生成包含一個重復值的集合。它需要兩個參數,第一個參數是任意類型的元素,第二個參數是生成的序列中所包含此元素的數量。下面的示例演示了使用Repeat來生成一個包含100的序列:

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("AsEnumerableTestWhere方法");

??? }

}

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將會保存一個類別對象。還有,如果Keynull,或者出現重復的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);

}

1.???????? 如果調用FirstOrDefault方法的序列為空,拋出異常

2.???????? 如果序列成功轉換為List<T>,并且元素數量大于0,則返回首個元素

3.???????? 如果序列沒有成功轉換為List<T>,則嘗試獲取序列的遍歷器,然后再調用遍歷器的MoveNext方法,如果返回值為true,則返回當前的元素。

4.???????? 如果上述操作都沒有執行,則使用default(T)關鍵字返回類型T的默認值

以下給出MSDN中,對于default(T)關鍵字的描述:

在泛型類和泛型方法中產生的一個問題是,在預先未知以下情況時,如何將默認值分配給參數化類型 T

  • 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;

}

以上代碼的執行過程為:

1.???????? 如果比較器為null,賦值為默認值EqualityComparer<TSource>.Default

2.???????? 如果序列1null,拋出異常。

3.???????? 如果序列2null,拋出異常。

4.???????? 遍歷序列1。在此過程中,如果序列2到達底端則返回false;如果序列1的當前值與序列2的當前值不同,則返回false

5.???????? 序列1遍歷完成后,如果序列2未到達底端,則返回false

6.???????? 如果第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都是基于這些操作符來完成各自豐富的功能。

轉載于:https://www.cnblogs.com/sunnycoder/archive/2010/01/17/1649831.html

總結

以上是生活随笔為你收集整理的LINQ标准查询操作符的全部內容,希望文章能夠幫你解決所遇到的問題。

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