我看到了一些不同的方法来迭代C#中的字典。有标准的方法吗?


当前回答

foreach(KeyValuePair<string, string> entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

其他回答

如果您试图在C#中使用通用字典,就像在另一种语言中使用关联数组一样:

foreach(var item in myDictionary)
{
  foo(item.Key);
  bar(item.Value);
}

或者,如果只需要遍历密钥集合,请使用

foreach(var item in myDictionary.Keys)
{
  foo(item);
}

最后,如果你只对价值观感兴趣:

foreach(var item in myDictionary.Values)
{
  foo(item);
}

(请注意,var关键字是可选的C#3.0及以上版本的特性,您也可以在此处使用键/值的确切类型)

字典<TKey, TValue>它是c#中的一个泛型集合类,它以键值格式存储数据。键值必须是唯一的,不能为null,而值可以是重复的和null。由于字典中的每个项都被视为KeyValuePair<TKey, TValue>表示键及其值的结构。因此我们应该采用元素类型KeyValuePair<TKey, 元素迭代期间的TValue>。下面是示例。

Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1,"One");
dict.Add(2,"Two");
dict.Add(3,"Three");

foreach (KeyValuePair<int, string> item in dict)
{
    Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}

最好的答案当然是:想一想,如果你计划迭代,你是否可以使用比字典更合适的数据结构-正如Vikas Gupta在问题讨论开始时已经提到的那样。但作为整个主题的讨论仍然缺乏令人惊讶的好选择。一个是:

SortedList<string, string> x = new SortedList<string, string>();

x.Add("key1", "value1");
x.Add("key2", "value2");
x["key3"] = "value3";
foreach( KeyValuePair<string, string> kvPair in x )
            Console.WriteLine($"{kvPair.Key}, {kvPair.Value}");

为什么它会被认为是在字典上迭代的代码味道(例如,通过foreach(KeyValuePair<,>)?

清洁编码的基本原则:“表达意图!”罗伯特·C·马丁在《干净的代码》中写道:“选择能揭示意图的名字”。很明显,单是命名太弱了。“表达(揭示)每一个编码决策的意图”更好地表达了这一点。

一个相关的原则是“最小惊讶原则”。

为什么这与遍历字典有关?选择字典表达了选择数据结构的意图,该数据结构主要用于按关键字查找数据。如今,.NET中有太多的替代方案,如果您想遍历键/值对,可以选择其他选项。

此外:如果您迭代某个项目,您必须揭示项目的排序方式和预期排序方式!尽管Dictionary的已知实现按照添加项的顺序对密钥集合进行排序-AFAIK,Dictionary没有关于订购的可靠规范(有吗?)。

但替代方案是什么?

TLDR:SortedList:如果您的集合没有变得太大,一个简单的解决方案是使用SortedList<,>,它还为键/值对提供了完整的索引。

微软有一篇关于提及和解释试衣系列的长文:键控集合

提到最重要的:KeyedCollection<,>和SortedDictionary<,>。SortedDictionary<,>比SortedList快一点,仅当它变大时才插入,但缺少索引,并且仅当插入的O(log n)优先于其他操作时才需要。如果您真的需要O(1)来插入并接受较慢的迭代,则必须使用简单的Dictionary<,>。显然,对于每种可能的操作,没有最快的数据结构。。

此外,还有ImmutableSortedDictionary<,>。

如果一个数据结构不是您所需要的,那么从Dictionary<,>或甚至从新的ConcurrentDictionary>派生,并添加显式迭代/排序函数!

我在MSDN上DictionaryBase类的文档中找到了此方法:

foreach (DictionaryEntry de in myDictionary)
{
     //Do some stuff with de.Value or de.Key
}

这是我唯一能够在从DictionaryBase继承的类中正确运行的一个。

有很多选择。我个人最喜欢的是KeyValuePair

Dictionary<string, object> myDictionary = new Dictionary<string, object>();
// Populate your dictionary here

foreach (KeyValuePair<string,object> kvp in myDictionary)
{
     // Do some interesting things
}

您也可以使用键和值集合