首页 > 解决方案 > IEnumerable.Count() 返回 0

问题描述

我有一个类型的变量,IEnumerable如果我Count()在 foreach 循环之前调用它的方法,那么它会返回正确的计数,但在 foreach 循环之后它返回 0。这是为什么呢?

[更新]

根据给出的答案,我发现我IEnumerable的东西是一次性的。所以我附上了我的代码,因为我已经将它转换为一个列表并返回为IEnumerable. 那么我在哪里做错了?

public async Task<IEnumerable<WorkItem>> Get(int[] workItemIds)
{
    return await context.WorkItems
                        .Where(it => workItemIds.Contains(it.Id))
                        .ToListAsync();
}

private async Task<int> ApproveOrRejectWorkItems(IEnumerable<WorkItem> workItems, int status)
{
    // var workItemsToBeUpdated = workItems.Count();
    workItems = workItems.Where(it => it.StatusId == (int)WorkItemStatus.Submitted);
    foreach (var workItem in workItems)
    {
        workItem.StatusId = status;
    }

    // here value becomes 0

    await _unitOfWork.WorkItemRepository.Update(workItems);

    return workItems.Count();
}

标签: c#asp.net.net

解决方案


您最有可能处理以下两种情况之一:

枚举之间的外部情况发生变化

请考虑以下场景:

var badRecords = repository.GetBadRecords(); //returns IEnumerable<T>
if(badRecords.Count() > n) 
{
  repository.DeleteBadRecords();
}

foreach( var badRecords in badRecords ) 
// This enumeration goes to the db again and selects 0 records because we just deleted them. 
{ 
  Log(badRecord);
};

解决办法是.ToList()尽早;

一次性发电机

这相似但略有不同,我们正在处理设计上只允许一次迭代的代码。

public static IEnumerable<int> GetAllNumbers(List<int> availableNumbers) {
    while(availableNumbers.Count > 0) 
    {
        var x = availableNumbers[0];
        availableNumbers.RemoveAt(0);
        yield return x;
    }
}

static void Main(string[] args)
{
    var numbers = GetAllNumbers(new List<int>{1,2,3});
    Console.WriteLine(numbers.Count()); // 3
    Console.WriteLine(numbers.Count()); // 0

    numbers = GetAllNumbers(new List<int>{1,2,3}).ToList();
    Console.WriteLine(numbers.Count()); // 3
    Console.WriteLine(numbers.Count()); // 3
}

Resharper 的IEnumerable警告的可能多重枚举

顺便提一句。Resharper 对此有专门的警告:Code Inspection: Possible multiple enumeration of IEnumerable


推荐阅读