【问题标题】:How to write LINQ query for getting object from another object using C#?如何编写 LINQ 查询以使用 C# 从另一个对象获取对象?
【发布时间】:2014-10-20 23:34:54
【问题描述】:

我已将以下 foreach 循环转换为 LINQ 语句。

foreach (Plant plant in Plant.ListPlants)
{
    foreach (Program program in plant.GetAllPrograms())
    {
        if (program.GetProfitCenter() != null)
        {
            foreach (CostCenter costCenter in program.GetProfitCenter().GetAllCostCenters())
            {
                foreach (Account account in costCenter.GetAccounts())
                {
                    if (account.Code == Code)//Code is a parameter
                    {
                        return account;
                    }
                }
            }
        }
    }
}

只要不存在此类帐户代码,结果也应返回 null。 请帮我为上述循环构建 LINQ。

【问题讨论】:

  • 我试过这个“ Plant.ListPlants.First(plant => plant.GetAllPrograms().First(program => program.GetProfitCenter() != null && program.GetProfitCenter().GetAllCostCenters( ).First(costCenter => costCenter.GetAccounts().First(account => account.Code == Code))));"但它显示无法将 Account 隐式转换为 bool
  • 有点难读,但我认为您需要在 costCenter => costCenter.GetAccounts().First(account => account.Code == Code) 周围添加 ()

标签: c# .net linq loops object


【解决方案1】:

使用SelectMany

var accounts = Plant.ListPlants
    .SelectMany(lp => lp.GetAllPrograms())
    .Where(p => p.GetProfitCenter() != null)
    .SelectMany(p => p.GetProfitCenter().GetAllCostCenters())
    .SelectMany(cc => cc.GetAccounts())
    .Where(acc => acc.Code == Code);
return accounts.FirstOrDefault();

【讨论】:

    【解决方案2】:

    这与您已经编写的代码没有什么不同,只是您在最后进行了所有过滤。

    var accounts = 
        from plant in Plant.ListPlants
        from program in plant.GetAllPrograms()
        from costCenter in program.GetProfitCenter().GetAllCostCenters()
        from account in costcenter.GetAccounts()
        where program.GetProfitCenter() != null && 
              account.Code == Code
        select account;
    return accounts.FirstOrDefault();
    

    我不能保证这会奏效,但它应该让您知道从哪里开始。

    【讨论】:

      【解决方案3】:
      return (from plant in Plant.ListPlants
      from program in plant.GetAllPrograms()
      where program.GetProfitCenter() != null
      from costCenter in program.GetProfitCenter().GetAllCostCenters()
      from account in costCenter.GetAccounts()
      where account.Code == Code
      select account).FirstOrDefault();
      

      这应该可行,我使用 ReSharper 功能将 foreach 转换为 LINQ,与 toadflakz 解决方案不同,它不应该在 program.GetProfitCenter() == null 时抛出异常。

      【讨论】:

      • 我选择了这个答案,因为我认为性能方面两者都是相同的,但不需要任何局部变量来存储中间结果,就像 Tim Schmelter 的答案一样。
      • @sanmathi: accounts 只存储查询,只有FirstOrDefault 会执行它。因此,使用变量可以提高可读性和可维护性(例如,如果您想在某个时候全部返回)并且无需任何成本。它还使调试更容易。
      • @sanmathi:由于 LINQ 的延迟执行,性能没有差异。查询本身(几乎)是无操作的。
      • @Tim Schmelter 是正确的,他的回答可能应该被接受,因为他发布得越早。我的只是省了一行代码,这里没什么区别。
      • 您可以从 Tim 的回答中内联变量(即 return Plants.ListPlants....Where(acc => acc.Code == Code).FirstOrDefault();)。这两个答案的真正区别在于 Michal 使用查询语法而不是方法语法(AKA fluent syntax AKA lambda 语法)(MSDN Article)。不同的人对这两种语法有不同的偏好,尽管有些查询在其中一种或另一种中更清晰。查询语法编译成方法语法,所以两者没有性能差异。
      猜你喜欢
      • 2022-01-09
      • 1970-01-01
      • 2013-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-24
      • 1970-01-01
      • 2011-09-08
      相关资源
      最近更新 更多