我一直在尝试很长时间来找到一个“干净”模式来处理.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