我希望我不会因为提出如此基本的问题而受到抨击。我可以通过 Google 搜索答案,但我想听听教科书中没有的内容。
我正在编写一个单元测试来验证我的 IDictionary
键是连续的。
自 Keys
属性是 ICollection<T>
,我想枚举集合并将键值打印到控制台。
尝试使用简单的 for
打印键值时循环:
for (int i = 0; i < unPivotedData.Count; i++)
{
Console.WriteLine(unPivotedData.Keys[i]);
}
我收到以下编译错误:
Cannot apply indexing with [] to an expression of type 'System.Collections.Generic.ICollection<int>'
但是,当我使用 foreach
循环:
foreach(int key in unPivotedData.Keys)
{
Console.WriteLine(key);
}
一切正常。
我了解索引器的作用及其实现方式,但 foreach
是如何实现的工作?我不明白 foreach
可以工作了 for
导致编译器错误。
我是否缺少枚举的基础知识?
干杯!
编辑:
此外,两者之间是否存在性能差异?我知道我不能使用 for
使用 IDictionary 但如果我使用 IList,我可以。 for
比 foreach
移动得更快还是性能提升可以忽略不计
最佳答案
foreach
只需要 IEnumerable
;而 for(a,b,c)
(在您的情况下)需要一个索引器属性。
当您在实现了 IEnumerable
的对象上调用 foreach
时,它会在后台调用 GetEnumerator()
,它会返回一个 IEnumerator。目的。该对象实现了一些成员,例如 MoveNext()
和 Current
。 foreach
的每次迭代实际上都在调用 MoveNext()
,如果枚举器可以向前移动,则返回 true
,如果不能,则返回 false (到达终点)。
这里的关键是实现IEnumerable
的对象不知道它有多少项,它所在的项的索引等。它所知道的只是它可以前进到下一个项目,将其作为当前项目返回,直到用完所有项目。
for(a,b,c)
循环,另一方面,本质上将永远循环 - 也就是说,它不受您可能碰巧迭代的集合的约束(尽管在实践中通常是)。在最基本的层面上,它每次执行一次C
,并检查B
是否为真。如果 B
为真,它将再次循环。如果它是假的,它将停止。每次循环时,在循环中您可能正在调用 object[number]
,如果您的对象没有这样的属性,这当然会失败。
这里的关键是带有索引器的对象支持随机访问 - 这意味着您可以在任何时候调用[arbitrary index]
并获取那个对象。将此与 IEnumerable
进行对比,后者同样只能访问当前 项。
关于c# - 枚举一个 IDictionary.Keys 集合,它是一个 ICollection<T>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1455901/