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 可以將集合內的元素轉換成新的樣式,如
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 可以將集合內符合條件的元素取出,如
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 可以獲得集合內的元素數量,如
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 可以將集合內的元素重新排序,如
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 邦幫忙鐵人賽
覺得LINQ Lambda 可讀性都超差,到現在還是搞不懂,像sql 標準語法就有一定的寫法可讀性百分之百,而且sql一些寫法join一堆表格一堆where條件,這些都不是linq寫的出來,感覺linq只能做一些簡單處理
LINQ Lambda就像是一個微軟自創的暗號,你必需用久然後死背,測試,一個程式不是很明確他的用法而是要透過測試才知道哦原來這個用法而非語法,只能說這個用法離開了微軟就變成廢物
我覺得你想得太嚴重了,對我來說 linq lambda 只是借用 SQL 的關鍵字(select, where...),來讓我們用類似 functional programming 的方式來操作集合而已,另外這是對集合的操作,而不是設計用來查詢大量的 table。
但像你提到的「sql一些寫法join一堆表格一堆where條件」,如果有這種需求我也習慣不用 lambda 的方式撰寫,那可讀性確實很差,但我們不是一定要這麼做。
離開微軟你還是可以在其他地方看到這種概念的產物,不論是 JS 的 map, filter... 還是 java stream 的 map, filter...,都是類似的行為,我會的語言不多只能舉幾個例。
希望上面的內容對你有幫助或者讓你改觀 :)