假设有一个函数返回一个延迟枚举的对象:

struct AnimalCount
{
    int Chickens;
    int Goats;
}

IEnumerable<AnimalCount> FarmsInEachPen()
{
    ....
    yield new AnimalCount(x, y);
    ....
}

您还有两个函数,它们使用两个单独的IEnumerables,例如:
ConsumeChicken(IEnumerable<int>);
ConsumeGoat(IEnumerable<int>);

如何调用ConsumeChickenConsumeGoat而不事先a)转换FarmsInEachPen()tolist(),因为它可能有两个无数的记录,b)没有多线程。
基本上:
ConsumeChicken(FarmsInEachPen().Select(x => x.Chickens));
ConsumeGoats(FarmsInEachPen().Select(x => x.Goats));

但没有强制双重枚举。
我可以用多线程来解决这个问题,但是对于每个列表使用一个缓冲队列会变得不必要的复杂。
因此,我正在寻找一种方法,将AnimalCount枚举数拆分为两个int枚举数,而不完全计算AnimalCount。在锁定步骤中同时运行ConsumeGoatConsumeChicken没有问题。
我能感觉到解决办法不在我掌握之中,但我还不完全在那里。我正沿着一个helper函数的思路思考,这个函数返回一个IEnumerable被输入到ConsumeChicken中,每次使用迭代器时,它都会在内部调用ConsumeGoat,从而在lock步骤中执行这两个函数。当然,除了,我不想给ConsumeGoat打不止一次电话。

最佳答案

我不认为有什么方法可以满足您的要求,因为ConsumeChickens(IEnumerable<int>)ConsumeGoats(IEnumerable<int>)是按顺序调用的,它们分别枚举一个列表—如果没有列表的两个单独枚举,您希望如何工作?
根据具体情况,更好的解决方案是使用ConsumeChicken(int)ConsumeGoat(int)方法(每个方法使用一个项),并交替调用它们。这样地:

foreach(var animal in animals)
{
    ConsomeChicken(animal.Chickens);
    ConsomeGoat(animal.Goats);
}

这将只枚举一次animals集合。
另外,需要注意的是:根据你的linq提供者以及你到底想做什么,可能会有更好的选择。例如,如果试图使用linq to sql或linq to entities从数据库中获取鸡和羊的总数,则执行以下查询。
from a in animals
group a by 0 into g
select new
{
    TotalChickens = g.Sum(x => x.Chickens),
    TotalGoats = g.Sum(x => x.Goats)
}

将生成一个查询,并在数据库端执行求和,这比在客户端拉取整个表并执行求和要好得多。

07-26 06:50