我写了以下linq语句,但我不禁觉得它可以以某种方式简化。目的是在List<IEnumberable<Counterparty>>
(查询中的对话框静态)对象中找到ClientId等于Counterparty.CounterpartyId的Orders。然后,这些订单应该更新ClientDesc字段以匹配Counterparty.DescriptionField。完成此操作后,我需要引发一个事件,传递所有已更新的订单。
如果不明显,OrderCache是一本字典。
以下是现有代码:
var updates = new List<Order>();
lock (CacheLock)
{
counterpartyStatic.ToList().ForEach(cachedList =>
cachedList.ToList().ForEach(
counterparty =>
{
var orders = OrderCache.Where(kvp => kvp.Value.Client == counterparty.CounterpartyId);
orders.ToList().ForEach(kvp =>
{
kvp.Value.ClientDesc = counterparty.Description;
updates.Add(kvp.Value);
});
}));
}
RaiseEvent(updates);
感谢您的帮助
答案 0 :(得分:4)
鉴于您的&#34;查询&#34;实际上是为了引起副作用(即:你在深度嵌套循环中改变了值的ClientDesc),我建议使用循环而不是尝试使用LINQ来编写它。这有几个好处 - 您不会仅仅使用List<T>.ForEach
制作列表,而且意图更加明确:
var updates = new List<Order>();
lock (CacheLock)
{
foreach(var cachedList in counterpartyStatic)
{
foreach(var counterparty in cachedList)
{
var orders = OrderCache.Where(kvp => kvp.Value.Client == counterparty.CounterpartyId);
foreach(var kvp in orders)
{
kvp.Value.ClientDesc = counterparty.Description;
updates.Add(kvp.Value);
}
}
}
RaiseEvent(updates);
}
这与原作一样短,但就发生的事情而言更为清晰。
关于为什么避免List<T>.ForEach
可能有益的论据,请参阅Eric Lippert's "foreach" vs "ForEach"。考虑到围绕它的问题,甚至已针对新的Windows应用商店应用删除了List<T>.ForEach
。
答案 1 :(得分:4)
(我写了一个很长的答案,然后我的笔记本电脑崩溃了.Grrr。)
我会编写一个LINQ查询来查找您感兴趣的所有值,然后单独执行变换。所以:
var query = from cachedList in counterpartyStatic
from counterparty in cachedList
join order in OrderCache.Values // Your query never uses the key
on counterparty.CounterpartyId equals order.Client
select new { Order = order, counterparty.Description };
var list = query.ToList(); // Avoid joining more than once
// Now do the update
foreach (var entry in list)
{
entry.Order.ClientDesc = entry.Description;
}
// Now raise the events
RaiseEvents(list => list.Select(entry => entry.Order)); // Add ToList if needed