這篇重點在IDE上看懂LINQ的Intellisense的提示內容,了解後就能看提示工具寫出需要的功能。
此篇用C#來使用LINQ。
本篇會帶出:
(1)LINQ是IEnumerable的擴充方法
(2)常見的三種委派→Func、Action、Predicate
(3)委派與Lambda的搭配
LINQ的 Intellisense內容
用LINQ中的.Where來說明,
我們將滑鼠移動到Where就可以看到如下圖白框的Intellisense(備註1)。
有沒有好大一串XD,好像每個字都能懂,但放在一起就不懂代表的意思。
沒關係我們一個個來拆解!
先看第二行:Filters a sequence of values based on a predicate.
說明.Where的作用→用bool運算式過濾一系列的值。
🛑接下來重點開始👇
將(extension)IEnumerable<int> System.Linq.Enumerable.Where<int>
(this IEnumerable<int> source, Func<int, bool> predicate)
拆解來看
(extension)
字義:擴充功能
代表擴充自IEnumerable
IEnumerable
可以說是集合的爸爸。
◾ 集合包含:陣列(Array)、清單(List)、字典(Dictionary)、佇列(Queue)、堆疊(Stack)…。
◾ 集合都有實作IEnumerable
。
◾ LINQ是針對IEnumerable寫出來的擴充方法,所以IEnumerable的子子孫孫(各種集合們)都可以用LINQ。
◾IEnumerable
自己的能力只有4個,其他都是靠擴充方法、LINQ。
問:IEnumerable有哪4個能力呢?
答:
◾IEnumerable
介面裡面有(1).GetEnumerator()
方法。
◾.GetEnumerator()
會回傳IEnumerator介面
。
◾IEnumerator
是定義了(2)MoveNext()
(3)Reset()
(4)屬性Current
的介面。
[參考:LINQ基礎 - IEnumerable & IEnumerator]
(1).GetEnumerator()
:Enumerator
可以看作一種指標的作用,可以依序指向集合中的每個物件。
GetEnumerator 方法提供了一種抽象的方式,用來指向集合中的元素,並提供對集合元素的訪問。透過遍歷器,可以依次訪問集合中的元素,而不需要知道集合的內部實現細節。
[參考:Micosoft文件─IEnumerable.GetEnumerator 方法]
(2)MoveNext()
:到下一個,會回傳bool告知向下移動是否成功,成功回傳true,到達終點會回傳false。
(3)Reset()
:回到最開頭。
(4)屬性Current
:取出來、回傳目前走訪到的值。
◾上述能力就讓人想到foreach,而foreach
背後邏輯就有使用MoveNext、Current。(備註2)
IEnumerable<T>
IDE知道x List型別是int,自動幫我們帶入型別<int>
。
System.Linq.Enumerable.Where<T>
這段說明.Where
擴充功能是在.Enumerable
類別中,.Enumerable類別
在System.Linq
命名空間中。
換順序說就是System.Linq
命名空間 中的.Enumerable
類別 中的.Where
擴充功能。
[資料來源:Microsoft文件─Enumerable 類別]
.Where
括號內的註解拆解
括號內提示我們要放的內容(this IEnumerable<int> source, Func<int, bool> predicate)
this IEnumerable<T> source
在LINQPad是灰色字,指的是x.Where
的x
。
在Visual Studio上則完全沒顯示這段文字。
而我們並不需要在括號內放關於這段的東西,只是提示前面的東西是什麼。
Func<T, bool>
◾Func
是常見的三種委派(delegate)→Func、Predicate、Action中的一種
◾ 看到委派可以搭配使用=>
(Lambda表達式)來創建委派實例,使語法更加簡潔明了,但Lambda不是必須的,也可以使用其他方式來創建委派實例。
◾<>
內有兩個型別,第一個型別T
代表傳入的型別,第二個型別bool
代表回傳的型別。
所以舉例當我們看到Intellisense.Where<T>(Func<T, bool> predicate)
可以在括號內放的內容。
e.g.,new[] {1, 2, 3, 4, 5}.Where(p => p > 3);
◾=>
左邊,p
是傳入參數T
型別,p
代表集合內的每個元素。
◾=>
右邊,放回傳bool
型別的運算式,因此放p > 3
。
◾ Microsoft共寫17種Func
,17種看起來很多,但其實很簡單XD
(1)Func<TResult>
→只放1個回傳參數,沒有傳入參數。
(2)Func<T,TResult>
→就是我們剛剛看的,1個傳入參數、1個回傳參數。
…不贅述 直接看第17種…
(17)Func<T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,TResult>
→16個傳入參數,1個回傳參數
predicate
◾ 在C#中代表可以傳入一個參數並返回bool值的方法。
◾ 此處predicate
作為Where方法的參數,以指定一個條件,用來過濾序列中的元素。
◾ 其他常見使用 Predicate 的 LINQ 方法:Any、All、Count、First、Last、Single…。
◾ Predicate如Func是常見的委派(delegate),並可以使用=>
(Lambda表達式)來創建委派實例。
Predicate有兩種寫法:
◾ 第一種,Func<T,bool> predicate
◾ 可以改成第二種,省略寫bool,把Func
改成Predicate
public void Hi(Func<char, bool> predicate)
{
}
//上下相等
public void Hi(Predicate<char> predicate)
{
}
比較三種委派Func、Predicate、Action
- 委派:在C#中是一種方法簽章的型別,可以儲存對方法的引用。
[參考:Microsoft文件─委派]
- Func:有回傳值的委派,通常用於查詢操作。
Func<T1,T2,…Tn,TResult>
- Predicate:帶有一個傳入參數並返回bool的委派,通常用於篩選操作。
Predicate<T>
- Action:沒有回傳值的委派,通常用於執行一個操作。
Action<T1,T2,…Tn>
◾ Action與Func一樣輸入參數最多16個。
- 範例:
public void Hi(Func<char, int> predicate)
{
}
public void HiHi(Predicate<char> predicate)
{
}
public void HiHiHi(Action<int, string, bool> x)
{
}
以上就是LINQ 的IntelliSense說明,
掌握這基本概念,就能看懂和使用LINQ了。
有學到新內容會再補充上來😊
◾ 大家想要在IDE上看IntelliSense ,可以用下面的程式碼。
這裡使用LINQPad(輕量型的IDE,相較開Visual Studio專案簡易,可以拿來執行小段程式碼。)
void Main()
{
var x = new List<int>{1,3,2,5,6,4};//建立一個List
x.Where(p => p>3 ).Dump();
//直接拿List來使用LINQ中的Where,找List中>5的數字
//在LINQPad用.Dump()來輸出,等於Visual Studio中Console.WriteLine()的能力,將文字印在Console上。
}
◾ 註解:
- IntelliSense
是程式碼輔助工具:列出成員、參數資訊、快速諮詢和自動完成文字。
有助於深入了解使用的程式碼、追蹤所鍵入的參數,以及幾個按鍵即可新增屬性和方法。
[資料來源:Microsoft文件──Visual Studio 中的 Intellisense]
2. foreach V.S. GetEnumerator
foreach (var element in x)
{
// do action
}
//等同下面的寫法
var enumerator = x.GetEnumerator();
while (enumerator.MoveNext())
{
var current = enumerator.Current;
// do action
}
謝謝觀看,此為新手的學習筆記整理,若有錯誤,煩請指正🙏