Я имею 3 (Редактирование) взаимоисключающий IEnumerables, которого я хочу выполнить итерации. Я хочу сделать что-то вроде этого:
IEnumerable<Car> redCars = GetRedCars();
IEnumerable<Car> greenCars = GetGreenCars();
IEnumerable<Car> blueCars = GetBlueCars();
foreach(Car c in (redCars + greenCars + blueCars)) {
c.DoSomething();
}
...
Лучшим способом я могу думать:
...
List<Car> allCars = new List();
allCars.AddRange(redCars);
allCars.AddRange(greenCars);
allCars.AddRange(blueCars);
foreach(car in allCars) {
...
}
...
Существует ли более краткий способ сделать это? Кажется, что combinding IEnumberables должен быть тривиальным.
С LINQ:
foreach(car in redCars.Concat(greenCars).Concat(blueCars)) {
//...
}
Для информации, разница между Union
и Concat
заключается в том, что Union
выполняет дополнительную работу, чтобы гарантировать уникальность; поэтому, если вы не ожидаете дубликатов (или, альтернативно: не обращайте на них внимания), то Concat
будет быстрее.
Используйте метод объединения LINQ.
foreach(Car c in redCars.Union(greenCars).Union(blueCars))
{
c.DoSomething();
}
Есть ли причина, по которой вам нужно делать это в одном цикле? Если да, то второй способ, вероятно, лучший. Нет ничего, что работало бы лучше, чем первый способ.
Если нет особой необходимости делать это в одном цикле, я бы сделал это в трех циклах, что было бы более эффективно по времени.
Как отмечалось в других ответах, Union выполняет дополнительную работу по устранению дубликатов, Concat просто объединяет последовательности. Однако, как я отметил в комментарии выше, глубокие вложенные конкатенации требуют больших затрат производительности. Вы также можете рассмотреть возможность использования SelectMany для сглаживания кучи итераторов:
var carLists = new[]{GetRedCars(), GetGreenCars(), GetBlueCars()};
var allCars = from carList in carLists
from car in carList
select car;
foreach(var c in allCars) { ... }
Вы можете счесть это более гибким, если обнаружите, что у вас на самом деле гораздо больше трех списков для итерации.