前言
有了Linq to Object之後,一切篩選的動作都變得相當平易近人,甚至上了癮,面對不必要的for loop總是會皺起眉頭。
今天這篇文章,則是針對當需要串起CheckBoxList的選取項目值時,怎麼樣用Linq來取代for loop。
需求
- CheckBoxList中,若Item被選取,則把值用逗號串起來。
之前沒有Linq的寫法
01 | /// <summary> |
02 | /// 使用foreach,判斷item是否selected, 將值加入List後,再轉成string array,使用string.join,透過string.join將值串起來 |
03 | /// </summary> |
04 | private void ForLoop() |
05 | { |
06 | var values = new List< string >(); |
07 | foreach (ListItem item in this .CheckBoxList1.Items) |
08 | { |
09 | if (item.Selected) |
10 | { |
11 | values.Add(item.Value); |
12 | } |
13 | } |
14 | var result = string .Join( "," , values.ToArray< string >()); |
15 | this .lblResult.Text = result; |
16 | } |
用Linq的寫法
碰到的問題:
1. this.CheckBoxList.Items,無法直接使用Where或Select的方法。
原因:為什麼無法用Where跟Select的方法呢?因為Where跟Select的方法,是屬於System.Linq這個namespace底下的擴充方法,目標為IEnumerable<T>,回傳也是IEnumerable<T>。
而因為Items的型別是ListItemCollection,來看一下ListItemCollection實作了哪些東西。
從上圖可以看到,ListItemCollection實作了IEnumerable,但為什麼沒有Where可以用?因為Where這個擴充方法是IEnumberable<T>才可以用。
那要怎麼轉成IEnumerable<T>呢?這邊用到的一樣是System.Linq底下的擴充方法Cast<T>。
可以看到,這個方法會將IEnumerable轉成IEnumerable<T>,轉成IEnumerable<T>之後,就可以使用Where與Select來篩選我們要的資料了。
1 | /// <summary> |
2 | /// 透過IEnumerable的Cast,轉成IEnumerable的泛型,就可以使用where, select等方法。直接將篩選結果轉成string array,透過string.join將值串起來 |
3 | /// </summary> |
4 | private void LinqCast() |
5 | { |
6 | var result = string .Join( "," , this .CheckBoxList1.Items.Cast<ListItem>().Where(x => x.Selected).Select(x => x.Value).ToArray< string >()); |
7 | this .lblResult.Text = result; |
8 | } |
結論
雖然只是個微不足道的範例跟小技巧,但卻可以透過這個範例來說明Cast<T>的方式,以及為什麼有些情況某些集合無法直接使用Where與Select的方法,為什麼這些extension method都要想辦法回傳IEnumerable<T>。
一切的根源,最後就會回到Linq的兩個主要介面:IEnumerable<T>與IEnumerator<T>的互動。
沒有留言:
張貼留言