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


当前回答

从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;
}

按以下方式遍历任何字典<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}");
}

其他回答

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

一般来说,在没有特定上下文的情况下要求“最佳方式”就像要求什么是最好的颜色?

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

另一方面,有很多方法可以在C#中迭代字典,没有最好的方法。这取决于需求,也常常取决于口味。

最直接的方式

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

从这些示例中可以看到更多真实世界的用例。如果您不需要特定的订单,只需坚持“最直接的方式”(见上文)!

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

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

正如在这个答案中已经指出的,KeyValuePair<TKey,TValue>实现了一个从.NET Core 2.0、.NET Standard 2.1和.NET Framework 5.0(预览版)开始的解构方法。

这样,就可以以KeyValuePair不可知的方式遍历字典:

var dictionary = new Dictionary<int, string>();

// ...

foreach (var (key, value) in dictionary)
{
    // ...
}

在.NET Framework 4.7中,可以使用分解

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

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

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