迭代字典的最佳方法是什么?


2625

我已经看到了几种不同的方法来迭代C#中的字典。有没有标准的方法?


108
令我惊讶的是,这个问题有很多答案,还有923次被赞成。(我用它来教课程)。我会争论,或者至少要补充一点,如果您必须遍历一本字典,那么您很可能是我不得不发表此评论,因为我发现字典以不适当的恕我直言的方式被滥用...是的,在很少情况下,当您迭代字典而不是查找字典时,情况就是如此它是为..设计的。请记住这一点,然后再想知道如何遍历字典。
Vikas Gupta 2014年

74
@VikasGupta当您不知道键将是什么时,您建议使用一组键值对来做什么?
nasch 2015年

26
@displayName如果您想对每个键-值对执行某项操作,但没有对用于查找值的键的引用,则可以遍历字典,对吗?我只是指出,尽管维卡斯(Vikas)声称这通常是不正确的用法,但有时您可能想要这样做。
nasch

34
要说它的用法不正确,意味着有更好的选择。那有什么选择呢?
凯尔·德莱尼

40
VikasGupta是错误的,我可以肯定地说,经过多年在非理论性场景下的高性能C#和C ++编程之后。实际上,确实经常发生这样的情况:创建字典,存储唯一的键值对,然后遍历这些值,事实证明这些值在集合中具有唯一的键。创建任何其他集合是避免字典迭代的真正低效且代价高昂的方法。请提供一个很好的替代方法,作为对问题的回答,以阐明您的观点,否则您的评论就太荒谬了。
sɐunıɔןɐqɐp

Answers:


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

29
如果我不完全了解字典中键/值的类型怎么办。var entry在这种情况下,使用效果更好,因此,我的确将回答这个问题而不是上面的观点。
Ozair Kafray

93
@OzairKafray var在您不知道类型时使用,通常是不好的做法。
Nate

52
这个答案是更好的,因为Pablo没有默认使用混淆返回类型的惰性编码器“ var”。
MonkeyWrench '16

119
@MonkeyWrench:嗯。Visual Studio知道类型是什么。您所要做的就是将鼠标悬停在变量上以进行查找。
罗伯特·哈维,2016年

31
据我了解,var只有在编译时知道类型的情况下才起作用。如果Visual Studio知道类型,那么您也可以找到它。
凯尔·德莱尼

866

如果您试图像在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及更高版本的功能,您也可以在此处使用键/值的确切类型)


11
第一个代码块最需要var功能:)
nawfal 2013年

27
我很欣赏这个答案指出您可以显式地遍历键或值。
Rotsiser Mho 2015年

11
我不喜欢在这里使用var。鉴于它只是语法糖,为什么在这里使用它?当某人试图阅读代码时,他们将不得不在代码中跳转以确定类型myDictionary(除非这是实际名称)。我认为在类型明显的情况下使用var很好,例如,var x = "some string"但在类型不明显的情况下使用var则好,我认为这是懒惰的编码,会损害代码阅读器/审阅者
James Wierzba

8
var我认为应该谨慎使用。特别是在这里,它不是建设性的:类型KeyValuePair可能与问题有关。
Sinjai

3
var有一个独特的目的,我不认为这是“句法”糖。有目的地使用它是一种适当的方法。
约书亚K

159

在某些情况下,您可能需要一个由for循环实现提供的计数器。为此,LINQ提供ElementAt了以下功能:

for (int index = 0; index < dictionary.Count; index++) {
  var item = dictionary.ElementAt(index);
  var itemKey = item.Key;
  var itemValue = item.Value;
}

21
要使用'.ElementAt'方法,请记住:using System.Linq; 在fx中不包含此功能。自动生成的测试类。
Tinia

14
如果您要修改与键关联的值,这就是方法。否则,在修改和使用foreach()时会引发异常。
Mike de Klerk

27
不是ElementAtO(n)运算吗?
Arturo TorresSánchez2015年

162
这个答案是完全不值得的。字典没有隐式顺序,因此.ElementAt在此上下文中使用字典可能会导致细微的错误。更为严重的是Arturo的观点。您将迭代字典dictionary.Count + 1时间,导致只应为O(n)的操作的O(n ^ 2)复杂度。如果您确实需要索引(如果这样做,那么您可能首先使用了错误的集合类型),则应该进行迭代dictionary.Select( (kvp, idx) => new {Index = idx, kvp.Key, kvp.Value})而不是.ElementAt在循环内使用。
支出者

5
ElementAt-o(n)操作!认真吗 这是不应执行此操作的示例。这么多投票?
Mukesh Adhvaryu,

96

取决于您要使用的是键还是值...

从MSDN Dictionary(TKey, TValue)类描述:

// When you use foreach to enumerate dictionary elements,
// the elements are retrieved as KeyValuePair objects.
Console.WriteLine();
foreach( KeyValuePair<string, string> kvp in openWith )
{
    Console.WriteLine("Key = {0}, Value = {1}", 
        kvp.Key, kvp.Value);
}

// To get the values alone, use the Values property.
Dictionary<string, string>.ValueCollection valueColl =
    openWith.Values;

// The elements of the ValueCollection are strongly typed
// with the type that was specified for dictionary values.
Console.WriteLine();
foreach( string s in valueColl )
{
    Console.WriteLine("Value = {0}", s);
}

// To get the keys alone, use the Keys property.
Dictionary<string, string>.KeyCollection keyColl =
    openWith.Keys;

// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach( string s in keyColl )
{
    Console.WriteLine("Key = {0}", s);
}

82

通常,在没有特定上下文的情况下询问“最佳方法”就像询问 最佳颜色是什么?

一方面,有很多颜色,没有最好的颜色。这取决于需求,通常也取决于口味。

另一方面,有很多方法可以迭代C#中的Dictionary,并且没有最佳方法。这取决于需求,通常也取决于口味。

最直接的方法

foreach (var kvp in items)
{
    // key is kvp.Key
    doStuff(kvp.Value)
}

如果您只需要该值(允许调用,则item比更具可读性kvp.Value)。

foreach (var item in items.Values)
{
    doStuff(item)
}

如果您需要特定的排序顺序

通常,初学者会对字典的枚举顺序感到惊讶。

LINQ提供了一种简洁的语法,该语法允许指定顺序(以及许多其他内容),例如:

foreach (var kvp in items.OrderBy(kvp => kvp.Key))
{
    // key is kvp.Key
    doStuff(kvp.Value)
}

同样,您可能只需要该值。LINQ还提供了一个简洁的解决方案:

  • 直接在值上进行迭代(允许调用item,比更具可读性kvp.Value
  • 但按键排序

这里是:

foreach (var item in items.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value))
{
    doStuff(item)
}

您可以从这些示例中获得更多实际应用案例。如果您不需要特定的订单,只需遵循“最直接的方法”(见上文)!


最后一个应该是.Values而不是select子句。
马菲

@Mafii您确定吗?OrderBy返回的值不是KeyValuePair类型,它们没有Value字段。我在这里看到的确切类型是IOrderedEnumerable<KeyValuePair<TKey, TValue>>。也许您还有其他意思?您可以写完整的行来显示您的意思(并进行测试)吗?
斯特凡纳·古里科

我认为这个答案包含了我的意思:stackoverflow.com/a/141105/5962841但是如果我感到困惑,请指正我
Mafii

1
@Mafii重新阅读我的全部答案,代码段之间的解释说明了上下文。您提到的答案就像我答案中的第二个代码部分(无需订购)。我刚刚按照items.Value您的建议写了。对于您评论的第四部分,这Select()是一种导致foreach直接枚举字典中的值而不是键值对的方法。如果在某种Select()情况下您不喜欢该示例,则可能更喜欢第三个代码部分。第四部分的要点是表明可以使用LINQ对集合进行预处理。
斯特凡纳·古里科

1
如果这样做,.Keys.Orderby()您将迭代键列表。如果这就是您所需要的,那就好。如果需要值,则在循环中,您必须查询每个键上的字典以获取值。在许多情况下,它并没有什么实际意义。在高性能方案中,它将。就像我在答案开头写道:“有很多方法(...),没有最好的方法。这取决于需求,通常也取决于味道。”
斯特凡纳·古里科

53

我会说foreach是标准方式,尽管它显然取决于您要查找的内容

foreach(var kvp in my_dictionary) {
  ...
}

那是您要找的东西吗?


42
嗯,将项目命名为“值”不是很令人困惑吗?通常,您将使用“ value.Key”和“ value.Value”之类的语法,这对将要阅读代码的其他人来说不是很直观,尤其是如果他们不熟悉.Net词典的实现方式时。
RenniePet 2014年

3
kvp在字典和相关数据结构上进行迭代时,@ RenniePet 通常用于命名KeyValuePair实例foreach(var kvp in myDictionary){...
mbx

37

您也可以在大型词典上尝试进行多线程处理。

dictionary
.AsParallel()
.ForAll(pair => 
{ 
    // Process pair.Key and pair.Value here
});

8
@WiiMaxx,更重要的是,如果这些项目彼此不依赖
Mafii

36

C#7.0引入了Deconstructors,如果您使用的是 .NET Core 2.0+应用程序,则该结构KeyValuePair<>已经Deconstruct()为您提供了一个。因此,您可以执行以下操作:

var dic = new Dictionary<int, string>() { { 1, "One" }, { 2, "Two" }, { 3, "Three" } };
foreach (var (key, value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}
//Or
foreach (var (_, value) in dic) {
    Console.WriteLine($"Item [NO_ID] = {value}");
}
//Or
foreach ((int key, string value) in dic) {
    Console.WriteLine($"Item [{key}] = {value}");
}

在此处输入图片说明


5
如果您使用的.NET Framework(至少为4.7.2)在KeyValuePair上没有解构,请尝试以下操作:foreach (var (key, value) in dic.Select(x => (x.Key, x.Value)))
nwsmith19年

29

我感谢这个问题已经得到了很多答复,但我想进行一些研究。

与对数组之类的对象进行迭代相比,对字典的迭代可能会比较慢。在我的测试中,数组上的迭代花费了0.015003秒,而字典(具有相同数量的元素)上的迭代花费了0.0365073秒,是它的2.4倍!尽管我看到了更大的差异。为了进行比较,列表在0.00215043秒之间的某个位置。

但是,这就像比较苹果和桔子。我的观点是,对字典进行迭代很慢。

字典针对查找进行了优化,因此考虑到这一点,我创建了两种方法。一个简单地执行foreach,另一个迭代键,然后查找。

public static string Normal(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var kvp in dictionary)
    {
        value = kvp.Value;
        count++;
    }

    return "Normal";
}

这个加载了键并在它们上进行了迭代(我也尝试过将键拉入string [],但是差别可以忽略不计。

public static string Keys(Dictionary<string, string> dictionary)
{
    string value;
    int count = 0;
    foreach (var key in dictionary.Keys)
    {
        value = dictionary[key];
        count++;
    }

    return "Keys";
}

在此示例中,正常的foreach测试使用0.0310062,而密钥版本使用0.2205441。加载所有键并遍历所有查找显然要慢很多!

对于最终测试,我已经执行了十次迭代,以查看此处使用键是否有任何好处(到目前为止,我很好奇):

如果可以,这是RunTest方法,可以帮助您直观地了解正在发生的事情。

private static string RunTest<T>(T dictionary, Func<T, string> function)
{            
    DateTime start = DateTime.Now;
    string name = null;
    for (int i = 0; i < 10; i++)
    {
        name = function(dictionary);
    }
    DateTime end = DateTime.Now;
    var duration = end.Subtract(start);
    return string.Format("{0} took {1} seconds", name, duration.TotalSeconds);
}

在这里,正常的foreach运行花费了0.2820564秒(比单次迭代花费的时间大约长十倍-正如您所期望的)。键上的迭代花费了2.2249449秒。

编辑添加: 阅读其他一些答案使我怀疑如果我使用词典而不是词典会发生什么。在此示例中,数组花费0.0120024秒,列表花费0.0185037秒,字典花费0.0465093秒。可以合理预期数据类型会影响字典的运行速度。

我的结论是什么?

  • 如果可以,请避免对字典进行迭代,因为它们比迭代具有相同数据的数组要慢得多。
  • 如果您确实选择对字典进行迭代,则不要尝试太聪明,尽管速度较慢,但​​比使用标准的foreach方法可能会做得多。

11
您应该使用StopWatch而不是DateTime进行测量:hanselman.com/blog/…–
甚至Mien,

2
您能描述一下您的测试方案,词典中有多少项,您运行方案多久计算一次平均时间吗?
WiiMaxx

3
有趣的是,根据字典中包含的数据,您将获得不同的结果。在字典上进行迭代时,枚举器函数必须跳过字典中的许多空插槽,这就是导致它比在数组上迭代慢的原因。如果字典已满,则要跳过的空插槽要少于一半的空插槽。
马丁·布朗

26

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

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

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

您还可以使用“键和值”集合


14

.NET Framework 4.7一个可以分解

var fruits = new Dictionary<string, int>();
...
foreach (var (fruit, number) in fruits)
{
    Console.WriteLine(fruit + ": " + number);
}

要使此代码在较低的C#版本上运行,请在System.ValueTuple NuGet package某处添加和编写

public static class MyExtensions
{
    public static void Deconstruct<T1, T2>(this KeyValuePair<T1, T2> tuple,
        out T1 key, out T2 value)
    {
        key = tuple.Key;
        value = tuple.Value;
    }
}

9
这是不正确的。.NET 4.7只是ValueTuple内置了。它可以作为nuget包用于早期版本。更重要的是,该Deconstruct方法需要C#7.0+ 才能用作的解构函数var (fruit, number) in fruits
David Arno

13

从C#7开始,您可以将对象解构为变量。我相信这是迭代字典的最佳方法。

例:

创建一个KeyValuePair<TKey, TVal>解构它的扩展方法:

public static void Deconstruct<TKey, TVal>(this KeyValuePair<TKey, TVal> pair, out TKey key, out TVal value)
{
   key = pair.Key;
   value = pair.Value;
}

Dictionary<TKey, TVal>以下列方式遍历任何对象

// Dictionary can be of any types, just using 'int' and 'string' as examples.
Dictionary<int, string> dict = new Dictionary<int, string>();

// Deconstructor gets called here.
foreach (var (key, value) in dict)
{
   Console.WriteLine($"{key} : {value}");
}

10

您建议在下面进行迭代

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

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

仅供参考,foreach如果值是object类型,则不起作用。


4
请详细说明:foreach如果哪个值是类型将不起作用object?否则,这没有什么意义。
Marc L.

9

迭代字典的最简单形式:

foreach(var item in myDictionary)
{ 
    Console.WriteLine(item.Key);
    Console.WriteLine(item.Value);
}

9

使用C#7,将此扩展方法添加到解决方案的任何项目中:

public static class IDictionaryExtensions
{
    public static IEnumerable<(TKey, TValue)> Tuples<TKey, TValue>(
        this IDictionary<TKey, TValue> dict)
    {
        foreach (KeyValuePair<TKey, TValue> kvp in dict)
            yield return (kvp.Key, kvp.Value);
    }
}


并使用这种简单的语法

foreach (var(id, value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


还是这个,如果您愿意

foreach ((string id, object value) in dict.Tuples())
{
    // your code using 'id' and 'value'
}


代替传统

foreach (KeyValuePair<string, object> kvp in dict)
{
    string id = kvp.Key;
    object value = kvp.Value;

    // your code using 'id' and 'value'
}


扩展方法将KeyValuePair您的IDictionary<TKey, TValue>转换为强类型tuple,使您可以使用这种新的舒适语法。

它将所需的字典条目仅转换为tuples,因此不会将整个字典转换为tuples,因此没有与此相关的性能问题。

tupleKeyValuePair直接使用直接调用相比,调用扩展方法来创建一个扩展仅需花费很少的钱,如果您要分配KeyValuePair的属性KeyValue反正新的循环变量。

实际上,此新语法非常适合大多数情况,但低级超高性能方案除外,在这种情况下,您仍然可以选择不直接在特定位置使用它。

签出:MSDN博客-C#7中的新功能


1
为什么选择“舒适的”元组而不是键值对的原因是什么?我在这里看不到收获。您的元组包含一个键和一个值,键-值对也是如此。
Maarten

4
嗨,马丁(Maarten),谢谢您的提问。主要好处是无需额外编程即可获得代码可读性。使用KeyValuePair时,必须始终使用表单,kvp.Keykvp.Value分别使用键和值。使用元组,您可以灵活地根据需要命名键和值,而无需在foreach块内使用其他变量声明。例如,您可以将键命名为factoryName,将值命名为,models当您获得嵌套循环(字典的字典)时,这尤其有用:代码维护变得容易得多。试一试!;-)
sɐunıɔןɐqɐp

7

我知道这是一个非常老的问题,但是我创建了一些可能有用的扩展方法:

    public static void ForEach<T, U>(this Dictionary<T, U> d, Action<KeyValuePair<T, U>> a)
    {
        foreach (KeyValuePair<T, U> p in d) { a(p); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.KeyCollection k, Action<T> a)
    {
        foreach (T t in k) { a(t); }
    }

    public static void ForEach<T, U>(this Dictionary<T, U>.ValueCollection v, Action<U> a)
    {
        foreach (U u in v) { a(u); }
    }

这样,我可以编写如下代码:

myDictionary.ForEach(pair => Console.Write($"key: {pair.Key}, value: {pair.Value}"));
myDictionary.Keys.ForEach(key => Console.Write(key););
myDictionary.Values.ForEach(value => Console.Write(value););

6

有时,如果只需要枚举值,请使用字典的值集合:

foreach(var value in dictionary.Values)
{
    // do something with entry.Value only
}

这篇文章报道说这是最快的方法:http : //alexpinsker.blogspot.hk/2010/02/c-fastest-way-to-iterate-over.html


+1可以提高性能。确实,如果只需要值,则对字典本身进行迭代确实会带来一些开销。这主要是由于将值或引用复制到KeyValuePair结构中。
Jaanus Varus 2015年

1
仅供参考,该链接中的最后一个测试是测试错误的东西:它测量对键的迭代,而不考虑值,而前两个测试确实使用值。
Crescent Fresh

5

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

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

这是我唯一能够在从DictionaryBase继承的类中正常运行的函数。


3
这看起来像使用非通用版本的Dictionary ...,即.NET Framework 2.0之前的版本。
joedotnot 2014年

@ joed0tnot:它是用于非仿制药版本Hashtable的对象
sɐunıɔןɐqɐp

5

foreach是最快的,如果只迭代___.Values,它也会更快

在此处输入图片说明


为什么要调用ContainsKey()for版本?这增加了您要比较的代码中不存在的额外开销。TryGetValue()存在以替换该确切的“如果键存在,则用键获取项目”模式。此外,如果dict包含从0到的连续整数范围dictCount - 1,您将知道索引器不会失败;否则,dict.Keys这就是您应该迭代的内容。无论哪种方式,都不需要ContainsKey()/ TryGetValue()不需要。最后,请不要发布代码的屏幕截图。
培根

3

我将利用.NET 4.0+的优势,并为最初接受的版本提供更新的答案:

foreach(var entry in MyDic)
{
    // do something with entry.Value or entry.Key
}

3

根据MSDN上的官方文档,迭代词典的标准方法是:

foreach (DictionaryEntry entry in myDictionary)
{
     //Read entry.Key and entry.Value here
}

2

我写了一个扩展来遍历字典。

public static class DictionaryExtension
{
    public static void ForEach<T1, T2>(this Dictionary<T1, T2> dictionary, Action<T1, T2> action) {
        foreach(KeyValuePair<T1, T2> keyValue in dictionary) {
            action(keyValue.Key, keyValue.Value);
        }
    }
}

那你可以打电话

myDictionary.ForEach((x,y) => Console.WriteLine(x + " - " + y));

您定义了ForEach一种您拥有的方法foreach (...) { }。似乎不必要。
马滕

1

如果说,您希望默认情况下遍历值集合,我相信您可以实现IEnumerable <>,其中T是字典中values对象的类型,而“ this”是Dictionary。

public new IEnumerator<T> GetEnumerator()
{
   return this.Values.GetEnumerator();
}

1

我只想加2分,因为大多数答案都与foreach-loop有关。请看下面的代码:

Dictionary<String, Double> myProductPrices = new Dictionary<String, Double>();

//Add some entries to the dictionary

myProductPrices.ToList().ForEach(kvP => 
{
    kvP.Value *= 1.15;
    Console.Writeline(String.Format("Product '{0}' has a new price: {1} $", kvp.Key, kvP.Value));
});

否则,这会增加一个“ .ToList()”调用,可能会稍微改善性能(如此处所指出的foreach与someList.Foreach(){}),尤其是在使用大型Dictionary并并行运行时选项/完全无效。

另外,请注意,您将无法在foreach循环内将值分配给'Value'属性。另一方面,您也可以操纵“键”,可能会在运行时遇到麻烦。

当您只想“读取”键和值时,也可以使用IEnumerable.Select()。

var newProductPrices = myProductPrices.Select(kvp => new { Name = kvp.Key, Price = kvp.Value * 1.15 } );

5
完全复制整个集合不会改善性能。它将极大地减慢代码的速度,并使几乎不占用额外内存的代码的内存占用量增加一倍。
Servy

我避免使用副作用“ List.ForEach”方法:foreach强制将副作用可见性提高到它所属的位置。
user2864740

0
var dictionary = new Dictionary<string, int>
{
    { "Key", 12 }
};

var aggregateObjectCollection = dictionary.Select(
    entry => new AggregateObject(entry.Key, entry.Value));

2
此答案中需要更多的理由/说明。会AggregateObject增加什么KeyValuePair?问题中所要求的“迭代”在哪里?
Marc L.

选择遍历字典并允许我们处理每个对象。它不如foreach,但我已经使用了很多。我的回答是否值得投票?
皮克斯

不,Select 使用迭代来影响结果,但它本身不是迭代器。迭代(foreach)用于的事物类型(尤其是具有副作用的操作)不在Linq的范围内,包括Select。在aggregateObjectCollection实际枚举之前,lambda不会运行。如果将此答案视为“第一条道路”(即在直道之前使用foreach),则会鼓励不良作法。有时,Linq操作可能迭代字典之前很有用,但是并不能解决所要求的问题。
Marc L.

0

Dictionary <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);
}

0

如果要使用for循环,可以执行以下操作:

var keyList=new List<string>(dictionary.Keys);
for (int i = 0; i < keyList.Count; i++)
{
   var key= keyList[i];
   var value = dictionary[key];
 }

但是,这样做有什么好处?它比foreach循环 更长,并且性能更差,因为它new List<string>(dictionary.Keys)dictionary.Count在您甚至没有机会对其进行迭代之前进行迭代。除了要求“最佳方式”是主观的,我不认为这将成为问题寻求的“最佳方式”还是“标准方式”。对于“如果要使用for循环...”,我将以“ 不要使用for循环” 来反驳。
培根

如果您有大量集合,并且foreach的操作速度很慢,并且在迭代时可以更改集合,则可以保护您免受“集合已更改”错误的影响,并且此解决方案比使用ElementAt更好。
SeçkinDurgay

我同意避免“例外”的例外是这样做的原因之一,尽管问题中未提到特殊情况,而且总是可以做到的foreach (var pair in dictionary.ToArray()) { }。不过,我认为最好在答案中阐明一个人想要使用此代码的特定场景以及这样做的含义。
培根

是的,你是正确的,但有一个答案在这里与ElementAt的,它有很高的声誉,我进入了这个答案:)
SeçkinDurgay

-1

简单的linq

 Dictionary<int, string> dict = new Dictionary<int, string>();
 dict.Add(1, "American Ipa");
 dict.Add(2, "Weiss");
 dict.ToList().ForEach(x => Console.WriteLine($"key: {x.Key} | value: {x.Value}") );

我看到您正在调用ToList()ForEach()是因为它仅在List<>类中定义,但是为什么要做所有这些而不是仅仅是foreach (var pair in dict) { }?我会说这甚至更简单,并且没有相同的内存/性能含义。无论如何,早在3 .5年前就已经在此答案中提出了这种精确的解决方案。
培根

仅出于代码可视化的目的,它确实可以按照您所指定的方式进行操作,我只是想以一种不同的方式来呈现它,并且我以更精简的观点表示歉意,因为没有看到所指出的答案,我很抱抱
Luiz FernandoCorrêaLeite

-3

除了排名最高的帖子外,还讨论了使用

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

要么

foreach(var entry in myDictionary)
{
    // do something with entry.Value or entry.Key
}

最完整的是以下内容,因为您可以从初始化中看到字典类型,kvp是KeyValuePair

var myDictionary = new Dictionary<string, string>(x);//fill dictionary with x

foreach(var kvp in myDictionary)//iterate over dictionary
{
    // do something with kvp.Value or kvp.Key
}

5
创建和复制第二个词典不是代码可读性的有效解决方案。实际上,我认为这会使代码更难理解,因为现在您必须问自己:“为什么最后一个家伙创建了第二本词典?” 如果您想更详细些,请使用选项一。
马修·古拉特

我只是想向您展示,当每个声明之前都声明时,声明中便清楚了foreach中的用法
BigChief
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.