在 C# 中动态“解压缩”IEnumerable 或最佳替代方案

2024-04-11

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

struct AnimalCount
{
    int Chickens;
    int Goats;
}

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

您还有两个函数,它们消耗两个单独的IEnumerables,例如:

ConsumeChicken(IEnumerable<int>);
ConsumeGoat(IEnumerable<int>);

你怎么能打电话ConsumeChicken and ConsumeGoat没有 a) 转换FarmsInEachPen()事先使用 ToList() ,因为它可能有无数条记录,b) 没有多线程。

基本上:

ConsumeChicken(FarmsInEachPen().Select(x => x.Chickens));
ConsumeGoats(FarmsInEachPen().Select(x => x.Goats));

但不强制双重枚举。

我可以用多线程来解决它,但是每个列表的缓冲队列都会变得不必要的复杂。

所以我正在寻找一种方法来分割AnimalCount枚举器一分为二int没有完全评估的枚举器AnimalCount。运行没有问题ConsumeGoat and ConsumeChicken步调一致地在一起。

我能感觉到解决方案就在我的掌握之外,但我还没有完全掌握。我正在考虑返回一个辅助函数IEnumerable被喂入ConsumeChicken每次使用迭代器时,它都会在内部调用ConsumeGoat,从而以锁步方式执行这两个函数。当然,除了我不想打电话ConsumeGoat不止一次..


我不认为有办法做你想做的事,因为ConsumeChickens(IEnumerable<int>) and ConsumeGoats(IEnumerable<int>)被顺序调用,每个都单独枚举一个列表 - 如果没有两个单独的列表枚举,您希望它如何工作?

根据具体情况,更好的解决方案是ConsumeChicken(int) and ConsumeGoat(int)方法(每个消耗一个single item),并交替调用它们。像这样:

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

将产生单个查询,并在数据库端进行求和,这比将整个表拉过来并在客户端进行求和要好得多。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 C# 中动态“解压缩”IEnumerable 或最佳替代方案 的相关文章

随机推荐