我一直在嘗試很長時間來找到一個「乾淨」模式來處理.SelectMany
與匿名類型,當你不總是想要返回結果。我最常見的使用案例如下所示:SelectMany匿名類型和跳過迭代
- 我們有一個我想要進行報告的客戶列表。
- 每位客戶的數據都駐留在一個單獨的數據庫中,因此我做了一個並行處理
.SelectMany
- 在每個lambda表達式中,我收集客戶對最終報告的結果。
- 如果一個特定的客戶應該被跳過,我需要返回一個空列表。
- 爲了快速報告我經常鞭打這些,所以我更喜歡匿名類型。
例如,邏輯可能看起來是這樣的:
//c is a customer
var context = GetContextForCustomer(c);
// look up some data, myData using the context connection
if (someCondition)
return myData.Select(x => new { CustomerID = c, X1 = x.x1, X2 = x.x2 });
else
return null;
這可以被實現爲foreach語句:
var results = new List<WhatType?>();
foreach (var c in customers) {
var context = GetContextForCustomer(c);
if (someCondition)
results.AddRange(myData.Select(x => new { CustomerID = c, X1 = x.x1, X2 = x.x2 }));
}
或者,它可以與.SelectMany
是實施用.Where
預過濾:
customers
.Where(c => someCondition)
.AsParallel()
.SelectMany(c => {
var context = GetContextForCustomer(c);
return myData.Select(x => new { CustomerID = c, X1 = x.x1, X2 = x.x2 });
})
.ToList();
這兩種方法都存在問題。 foreach
解決方案需要初始化List
來存儲結果,並且您必須定義類型。 .SelectMany
與.Where
通常不切實際,因爲someCondition
的邏輯相當複雜,並且取決於某些數據查找。所以,我的理想的解決方案將是這個樣子:
customers
.AsParallel()
.SelectMany(c => {
var context = GetContextForCustomer(c);
if (someCondition)
return myData.Select(x => new { CustomerID = c, X1 = x.x1, X2 = x.x2 });
else
continue? return null? return empty list?
})
.ToList();
我放在else
線什麼跳過一個返回值?該解決方案中沒有我可以拿出工作或理想:
continue
不能編譯,因爲它不是一個積極的foreach
循環return null
導致NRE
return
空單需要我初始化再次列出匿名類型。
有沒有辦法完成上述的乾淨,簡單,整潔,並滿足我所有(挑剔)的要求?
這將導致大量的動態調用,並反過來反射。在性能方面,這不是最好的選擇。 – Athari
好點。但他也表示他只是需要這個來產生一些快速報告。 –
我最喜歡這個解決方案,因爲它很短,不需要任何自定義的擴展方法。我嘗試了'Enumerable.Empty()',但它不能確定類型,沒有''。謝謝!! –
mellamokb