小技巧-當集合型別不支援 LINQ 擴充方法

用慣 LINQ 後不太能忍受回頭用 foreach 處理集合物件,List<T>、IEnumerable<T> 及物件陣列可直接 Where()、Select() ,基本上涵蓋大部分應用情境,但有些時候還是會遇到一些不支援 LINQ 擴充方法的集合物件。這篇筆記將介紹透過簡單轉換讓集合支援 LINQ 的小技巧。(別像我以前傻傻先 var list = new List<T> 再 foreach 跑 list.Add(…) )

舉兩個我遇過的例子。

有字串 A12+A34+B99-C56+A87,打算用 Regex.Matches 挑出 A 起首的數字代碼,用 Select().ToArray() 轉成字串陣列 "12","34","87"。

有 app.config 如下,我想透過 System.Configuration.ConfigurationManager.AppSettings 將 d:SvcIp d:SvcPort 設定用 ToDictionary() 轉成 Dictionary<string, string>。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="d:SvcIp" value="192.168.1.87" />
    <add key="d:SvcPort" value="80" />
    <add key="Interval" value="5000" />
  </appSettings>
</configuration>

依直覺寫出以下程式碼,但無法編譯,理由是 MatchCollection 跟 NameValueCollection 兩種集合型別不適用 LINQ 擴充方法。

.Select() 是 IEnumerable<TSource> 的擴充方法,而 MatchCollection 只實作了 ICollection 與 IEnumerable 介面,故無法直接使用 Select、Where、ToList 等 LINQ 擴充方法:

.Cast<T>() 是 IEnumerable 的擴充方法,可將 IEnumerable 轉換成 IEnumerable<TResult>,如此即可大方使用 LINQ 方法加工。

NameValueCollection 是另一種案例,它繼承自 NameObjectCollectionBase,NameObjectCollectionBase 雖然實作了 IEnumerable,但其 GetEnumerator() 傳回 IEnumerator 只能取回 Name 字串,充其量 Cast<string> 跟 AllKeys 相比多此一舉,故我們改對 AllKeys(型別為 string[],陣列型別可使用 LINQ 擴充方法)進行 Select 產生 Key Value 物件,再依原本構想進行 Where() 篩選與 ToDictionary() 轉換。

補充一點,appSettings 不接受同一 key 值設定多次,遇重複 key 時以最後一次 value 為準,故 appSettings 設定永遠是一對一。但 NameValueCollections 本身允許同一 key 值對應多組 value,透過 Get("key") 取得 "value1,value2,value3" 以逗號分隔的字串,GetValues("key") 則傳回 "value1", "value2", "value3" 字串陣列,如要轉換成 Dictionary<string, string>需考量此一狀況。

最後再來個練習,DataTable.Rows 的型別為 DataRowCollection,其父類別 InternalDataCollectionBase 實作了 ICollection, IEnumerable,跟 MatchCollection 狀況相同,解法也一樣,Cast<DataRow> 後可使用 Select(),若想套用我很愛的 ForEach() 方法,則用 ToList() 轉型成 List<DataRow> 即可如願~ 〔註: ForEach() 非 IEnumerable<T> 的擴充方法,為 List<T> 的專屬方法〕

歡迎推文分享:
Published 14 September 2017 11:40 PM 由 Jeffrey
Filed under:
Views: 6,912



意見

沒有意見

你的看法呢?

(必要的) 
(必要的) 
(選擇性的)
(必要的) 
(提醒: 因快取機制,您的留言幾分鐘後才會顯示在網站,請耐心稍候)

5 + 3 =

搜尋

Go

<September 2017>
SunMonTueWedThuFriSat
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567
 
RSS
創用 CC 授權條款
【廣告】
twMVC

Tags 分類檢視
關於作者

一個醉心技術又酷愛分享的Coding魔人,十年的IT職場生涯,寫過系統、管過專案, 也帶過團隊,最後還是無怨無悔地選擇了技術鑽研這條路,近年來則以做一個"有為的中年人"自許。

文章典藏
其他功能

這個部落格


Syndication