iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 22
1

LINQ

Language Integrated Query (LINQ) 是一組以直接將查詢功能整合至 C# 語言為基礎之技術的名稱。
「查詢」是指從資料來源中擷取資料的運算式。查詢通常以特定的查詢語言來表示。
查詢運算式使用類似 SQL 或 XQuery 的宣告式語法來查詢 IEnumerable 集合。
透過 LINQ,查詢現在已成為第一級的語言建構,就如同類別、方法、事件等等。
在編譯時期,查詢語法會轉換成對 LINQ 提供者實作的標準查詢運算子擴充方法進行的方法呼叫。

簡單說就是 C# 的資料查詢語法,任何實作 IEnumerable 的集合都可以操作,本篇會用 Lambda 來撰寫 LINQ。

使用前需先引用命名空間 System.Linq

既然提到了資料查詢,有學過 SQL 的都知道 SELECT, FROM, WHERE 這三個關鍵字吧。所以你應該看得懂官方的範例

int[] scores = new int[] { 97, 92, 81, 60 };

// Define the query expression.
IEnumerable<int> scoreQuery =
    from score in scores
    where score > 80
    select score;

但今天並不是要教你這樣撰寫,而是使用 Lambda,將 LINQ 改寫成

int[] scores = new int[] { 97, 92, 81, 60 };

// Define the query expression.
var scoreQuery = scores
  .Where (x => x > 80)
  .Select (x => x);

scores 為欲查詢集合,Where 引數為 Predicate 提供給他一個篩選條件,Select 引數為 Func 告訴他我們需要傳回什麼內容,忘了 Predicate 與 Func 可以看 DAY 17 委派的介紹。

個人覺得 Lambda 可讀性比較好,比較 Functional。

Select

Select 可以將集合內的元素轉換成新的樣式,如

int[] scores = new int[] { 97, 92, 81, 60 };

var scoresAdd2 = scores
  .Select (x => x + 2);

var scoresToString = scores
  .Select (x => x + "");

也可以更改集合成員內容,傳回一個匿名類型如

var members = new List<Member> () {
  new Member () { ID = 0, Name = "Mio" },
  new Member () { ID = 1, Name = "Miffy" },
  new Member () { ID = 2, Name = "Lulu" },
  new Member () { ID = 3, Name = "NekoSan" }
};

var names = members
  .Select (x => x.Name);
var membersAddProperty = members
  .Select (x =>
    new {
      ID = x.ID,
      Name = x.Name,
      IDName = $"ID = {x.ID}, Name = {x.Name}"
});

Where

Where 可以將集合內符合條件的元素取出,如

var members = new List<Member> () {
  new Member () { ID = 0, Name = "Mio" },
  new Member () { ID = 1, Name = "Miffy" },
  new Member () { ID = 2, Name = "Lulu" },
  new Member () { ID = 3, Name = "NekoSan" }
};

var membersNameContainsMi = members
  .Where (x => x.Name.Contains ("Mi"));

與 Select 差別可以說是,Where 負責垂直篩選,Select 負責水平篩選,在 LINQ 裡面這兩個可以說是最常使用的方法。

另外 x 這個變數是隨意取的,你可以取任何你想取的名稱,可以想像成是集合中的每一個元素。

在 Select 與 Where 方法中,你也可以再傳入一個 int 變數,代表在集合中的索引位置如

int[] scores = new int[] { 97, 92, 81, 60 };

var scoresAddNo = scores
  .Select ((x, y) => new { score = x, No = y });

var scoresWhereNo2 = scores
  .Where ((x, y) => y == 2);

Count

Count 可以獲得集合內的元素數量,如

var members = new List<Member> () {
  new Member () { ID = 0, Name = "Mio" },
  new Member () { ID = 1, Name = "Miffy" },
  new Member () { ID = 2, Name = "Lulu" },
  new Member () { ID = 3, Name = "NekoSan" }
};

var membersCount = members
  .Count ();

甚至是集合內符合條件的元素數量。

var membersNameContainsMiCount = members
  .Count (x => x.Name.Contains ("Mi"));

OrderBy

OrderBy 可以將集合內的元素重新排序,如

int[] scores = new int[] { 97, 92, 81, 60 };

var scoresAddNoOrderByScore = scores
  .Select ((x, y) => new { score = x, No = y })
  .OrderBy (x => x.score);

一些小結論

今天介紹了 LINQ 是什麼以及基礎用法,明天也會繼續講說一些常用的方法,如果對 LINQ 有興趣的朋友,大力推薦下面去年鐵人賽的文章,這位大大寫的超級詳細,包含昨天的內容 foreach 與 yield,也介紹了 LINQ 原碼,鐵人賽有很多很棒的文章可以挖掘。

對了,在使用 LINQ 時,永遠是以傳回值的方式進行,所以不會去更改原本的集合,並且傳回的是 IEnumerable 類型,這類型特性是什麼昨天也提過了,忘記可以回去看唷。

忘了介紹可能很多人在意的事情,那就是 LINQ 的念法,這與 Link 同音,所以不要念成 Lin Q 了。

感謝閱讀。

參考資料
Language-Integrated Query (LINQ) (C#) | Microsoft Docs
LINQ 查詢簡介 (C#) | Microsoft Docs
支援 LINQ 的 C# 功能 | Microsoft Docs
深入探索LINQ | 2018 iT 邦幫忙鐵人賽


上一篇
DAY 21 迭代器
下一篇
DAY 23 LINQ 查詢運算式(二)
系列文
.net 後端起手式 30天認識 C# 30

尚未有邦友留言

立即登入留言