1

给定一个如下所示的对象图;

A --> B[] --> B1[]
          --> B2[]   
  --> C[]

我需要检查 B1 和 B2 的成员/属性的某些条件,并确保 b2.Code 出现在 C[] 中的某个位置。如果所有条件都满足,那么我需要使用来自 C 和 B 数组元素的变量来构造一个新对象。我目前的尝试如下所示,但我想知道这是否可以用 LINQ 更简洁?

   A a = GetA();
   List<MyTest> tsts = new List<MyTest>();
   foreach (B b in a.B)
    {
        foreach (B1 b1 in b.B1)
        {
            if (b1.State == ("READY"))
            {
                foreach (B2 b2 in b.B2)
                {
                    var tst = (from c in a.C
                           where c.Code == b2.Code && !c.IsRedundant
                           select new MyTest
                           {
                               Code = c.Code,
                               BVal = b.BVal,
                               C1Val = c.C1                     
                           }).FirstOrDefault();
                    if (tst != null)
                        tsts.Add(tst);
                    break;
                }
            }
        }
    }
4

1 回答 1

2

绝对地。基本上每个新foreach的大致相当于一个额外的from子句:

var tests = from b in GetA().B
            from b1 in b.B1
            where b1.State == "READY"
            from b2 in b.B2.Take(1)
            from c in a.C
                       .Where(x => x.Code == b2.Code && !c.IsRedundant)
                       .Take(1)
            select new MyTest
            {
                Code = c.Code,
                BVal = b.BVal,
                C1Val = c.C1                     
            };

var testList = tests.ToList();

对此有几点说明:

  • 您从未真正使用 似乎很奇怪b1,但是您将为每个b1处于“就绪”状态的测试创建一组额外的测试。
  • break循环内的无条件foreach (B2 b2 ...)基本上意味着我们只执行一次循环体 - 因此Take(1)
  • 您只使用最内层查询的第一个结果的方式就是为什么我有内部查询(通过扩展方法表示)并Take(1)调用最多获得一个结果

很可能可以删除其中一些奇怪的东西 - 但目前尚不清楚您真正想要实现的目标是什么,所以我只是试图让代码尽可能忠实地重现您的原始查询。

于 2011-08-04T06:03:39.923 回答