简化Linq声明

时间:2012-08-23 15:59:18

标签: linq c#-4.0 linq-to-objects

我写了以下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);

感谢您的帮助

2 个答案:

答案 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