foreach Dictionary<>.Values 或 foreach Dictionary<>

Pap*_*ter 2 c# iteration foreach containers

我想知道DictionaryC#中这两种迭代集合样式的细节:

Dictionary<X, Y> xydic = new Dictionary<X, Y>();
Run Code Online (Sandbox Code Playgroud)

款式一:

foreach (Y y in xydic.Values) { use y }
Run Code Online (Sandbox Code Playgroud)

款式二:

foreach (var it in xydic) { Y y = it.Value; use y... }
Run Code Online (Sandbox Code Playgroud)

我多年来一直是 C++ 开发人员(现在我在一个 C# 项目中工作),但我不知道Dictionary集合如何工作、内存布局或元素如何迭代的细节,所以我想知道:

xydic.Values创建一个临时List<Y>? 我在文档中没有看到有关创建临时列表的任何信息。

如果创建了一个临时列表,这是否意味着该集合被迭代两次:第一次创建List<Y>,第二次迭代列表本身?

如果上述问题的答案是肯定的,那么第二种风格应该更有效,使第一种风格几乎无用,所以我认为我在某种程度上应该是错误的。

我觉得这个问题应该在某个地方得到回答,但我找不到答案。

Jep*_*sen 5

检索 a 的.Values属性Dictionary<,>是一个 O(1) 操作(记录)。嵌套类型Dictionary<,>.ValueCollection是字典的简单包装器,因此在创建它时没有迭代。

在调用 时GetEnumerator(),您将获得嵌套的嵌套Dictionary<,>.ValueCollection.Enumerator结构的实例。它直接通过acccesses条目private阵列entriesDictionary<,>

你可以看到源代码

所以你上面的“风格一”是一种很好的、​​清晰的做事方式,没有性能开销。

请注意,获取值的顺序是任意的。您不知道底层数组entries是如何组织的,一旦在Dictionary<,>开始之前进行了多次插入和删除foreach

但是,“样式一”和“样式二”的顺序是相同的;两者都以相同的方式访问 的私有entries数组Dictionary<,>