Упрощение кода с помощью LINQ (коллекции в коллекциях) - PullRequest
1 голос
/ 04 августа 2011

Учитывая граф объектов, который выглядит примерно так:

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;
                }
            }
        }
    }

1 Ответ

2 голосов
/ 04 августа 2011

Абсолютно.По сути, каждый новый 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)получить не более одного результата

Вполне возможно, что некоторые из этих странностей могут быть удалены - но неясно, чего вы на самом деле пытаетесь достичь, поэтому я просто попытался создать кодкак можно точнее воспроизведите исходный запрос.

...