这如何不会导致 IEnumerable 的多个枚举
本文关键字:枚举 IEnumerable 何不会 | 更新日期: 2023-09-27 18:36:17
我最初将参数类型设置为ICollection,因为我认为我会遇到IEnumerable的多个枚举的问题。 但是,Resharper 建议我可以将参数类型转换为 IEnumerable。 我最终做了一个测试来仔细检查,它似乎工作正常:
private static void Main(string[] args)
{
var nums = GetNums();
MultipleEnumerations(nums);
Console.ReadLine();
}
private static void MultipleEnumerations(IEnumerable<int> nums)
{
var otherNums = new List<int> {1, 2, 3, 4, 5};
var filtered = otherNums.Where(num => nums.Contains(num));
foreach (var num in filtered)
{
Console.WriteLine(num);
}
}
private static IEnumerable<int> GetNums()
{
yield return 4;
yield return 2;
}
这如何不会导致 IEnumerable 的多个枚举?
这确实会导致可枚举项的多个枚举。
如果我将您的代码更改为以下内容:
private static void MultipleEnumerations(IEnumerable<int> nums)
{
var otherNums = new List<int> { 1, 2, 3, 4, 5 };
var filtered = otherNums.Where(num =>
{
Console.WriteLine("{0}?", num);
return nums.Contains(num);
});
foreach (var num in filtered)
{
Console.WriteLine(num);
}
}
private static IEnumerable<int> GetNums()
{
Console.WriteLine("4!");
yield return 4;
Console.WriteLine("2!");
yield return 2;
}
。然后我可以得到以下输出:
1?4!2!2?4!2!23?4!2!4?4!45?4!2!
您可以看到,对于正在测试的每个otherNums
,它每次都在运行nums
(这是GetNums
)。当测试4
它只需要第一个nums
数,但除此之外,它会完全迭代5次。
如果你想知道为什么.Where
和foreach
都不迭代otherNums
那是因为.Where
是使用延迟执行模型运行的 - 只有当你执行foreach
或类似.ToList()
时,它才会执行。
Resharper可能建议将参数的类型更改为IEnumerable
,因为没有调用者会传递(派生自)IEnumerable
以外的其他类型,Resharper建议使用最简单的类型。
ICollection
仅向派生IEnumerable
添加几个属性和方法,最重要的是 Count
属性。
根据此表,对于实现ICollection
的大多数类,GetEnumerator()
方法具有相同的复杂性。