Все решения, опубликованные до сих пор, являются специализированными - они не являются общими или общими, и, таким образом, в следующий раз, когда у вас будет иерархический список, вам придется кодировать новое решение.Тьфу.
Вот общее, общее решение, которое будет работать для всех ваших иерархических потребностей:
public static IEnumerable<T> Flatten<T>(this IEnumerable<T> sequence, Func<T, IEnumerable<T>> childFetcher)
{
var itemsToYield = new Queue<T>(sequence);
while (itemsToYield.Count > 0)
{
var item = itemsToYield.Dequeue();
yield return item;
var children = childFetcher(item);
if (children != null)
{
foreach (var child in children)
{
itemsToYield.Enqueue(child);
}
}
}
}
Вот как вы будете его использовать:
myList.Flatten(i => i.SubEntries).FirstOrDefault(i => i.HighScore);
Легкоas cheese.
Этот метод расширения можно использовать для преобразования любых иерархических данных в плоский список, в котором их можно искать с помощью LINQ.
Еще одна замечательная особенность этого решения заключается в том, что оно использует ленивую оценку, поэтому оно выполняет столько работы, сколько требует вызывающий.Например, в приведенном выше коде Flatten прекратит сбор элементов, как только будет найден HighScore.
Это решение также позволяет избежать рекурсии, что может быть дорогостоящей операцией для глубоко вложенных иерархий, избегая многократного выделения стекачто рекурсивные решения возникают.