C# 生成单个项目并向前移动计数器

C# 生成单个项目并向前移动计数器,c#,dictionary,yield,consumer,producer,C#,Dictionary,Yield,Consumer,Producer,我正在处理一个问题,我需要一次向消费者提供一个项目,并将计数器向前移动,以便下一个项目等,直到项目用完。我提出了代码的初稿(见下文)。底层数据结构包含一个字典,其中字符串作为键,另一个字典作为值,该字典保存实体类型的对象 我有一种感觉,我确实需要以某种方式维护状态,所以我尝试使用yield-return语句,但不确定如何将其组合在一起。另外,我认为使用forearch/iterator可能需要调整,因为消费者将调用GetNextItem(),直到它返回false(表示项目用完) 私有静态字典dt

我正在处理一个问题,我需要一次向消费者提供一个项目,并将计数器向前移动,以便下一个项目等,直到项目用完。我提出了代码的初稿(见下文)。底层数据结构包含一个字典,其中字符串作为键,另一个字典作为值,该字典保存实体类型的对象

我有一种感觉,我确实需要以某种方式维护状态,所以我尝试使用yield-return语句,但不确定如何将其组合在一起。另外,我认为使用forearch/iterator可能需要调整,因为消费者将调用GetNextItem(),直到它返回false(表示项目用完)

私有静态字典dt;
私有uint localCounter=0,globalCounter=0;
公共实体GetNextItem()
{
foreach(dt.Keys中的字符串键)
{
如果(MoveCounters(key))//计数器已移动,则处理下一项
{
收益返回dt[键][本地计数器];
}
}
}
专用布尔移动计数器(字符串键)
{
如果(++globalCounter>dt.Count)返回false;//达到极限
如果(++localCounter>dt[key].Count)
{
globalCounter++;
返回true;
}
localCounter++;
返回true;
}
}
公共类实体
{
Dictionary dtValues;//包含CSV文件中的值。
}

移动到下一个子列表时,无法将
本地计数器
重置为零

也就是说,您可以更轻松地执行此操作:

foreach (var subdt in dt.Values)
   foreach (var item in subdt.Values)
       yield return item;
但是使用LINQ
SelectMany更容易

return dt.Values.SelectMany(subdt => subdt.Values);
请注意,最后一个不使用
产生返回值
,因为LINQ产生可枚举值,而您只返回它

如果还要记录密钥和计数器,请尝试以下操作:

int iList = 0;
foreach( var subdt in dt ) {
    /* log iList, subdt.Key */
    int iItem = 0;
    foreach( var item in subdt.Value ) {
       /* log iItem, item.Key */
       ++iItem;
       yield return item.Value;
    }
    ++iList;
}

你在哪里给字典加键。。?你不能这样做吗
返回dt.Add(dt[key][localCounter])类似的东西..?键将单独添加,就像两次传递系统一样。先把字典填好,然后一旦填好,制作人就可以给你上。谢谢。我想知道,如果产量增加,我可以跟踪哪些项目已处理?对于计数器,通过查看两个计数器的值,我总是知道这一点。我正在考虑维护一个列表,并在其中放入某种值来跟踪它,并在yield return语句之前使用它。@用户:您肯定可以在foreach循环中使用计数器,或者使用keys或KeyValuePair对象。我将添加一个示例。最大的改进是让
foreach
为您找到每个子列表的末尾。
int iList = 0;
foreach( var subdt in dt ) {
    /* log iList, subdt.Key */
    int iItem = 0;
    foreach( var item in subdt.Value ) {
       /* log iItem, item.Key */
       ++iItem;
       yield return item.Value;
    }
    ++iList;
}