![](/img/trans.png)
[英]Define an Extension Method for IEnumerable<T> which returns IEnumerable<T>?
[英]IEnumerable<T>.Count() returns 0
我有一个IEnumerable
类型的变量,如果我在 foreach 循环之前对其调用Count()
方法,那么它会返回正确的计数,但在 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();
}
您很可能正在处理以下两种情况之一:
请考虑以下情况:
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 对此有专门的警告: Code Inspection: Possible multiple enumeration of IEnumerable
感谢您澄清您是在Get()
方法中具体化列表后过滤列表。
您的问题是 LINQ 是一个视图。 因此,如果您将IEnumerable
迭代两次,它将 go 遍历源项两次,对源项应用任何过滤器、投影等。 这意味着通过更改源项目,可枚举将在您第二次迭代时产生不同的项目,因为这些项目不再与过滤器匹配。
我建议您将方法修改为:
private async Task<int> ApproveOrRejectWorkItems(IEnumerable<WorkItem> workItems, int status)
{
var workItemsToBeUpdated = workItems.Count();
foreach (var workItem in workItems.Where(it => it.StatusId == (int)WorkItemStatus.Submitted))
{
workItem.StatusId = status;
}
await _unitOfWork.WorkItemRepository.Update(workItems);
return workItems.Count();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.