【问题标题】:Are elements in a .NET's Dictionary sequential? [duplicate].NET 字典中的元素是连续的吗? [复制]
【发布时间】:2013-10-03 00:52:03
【问题描述】:

说,如果我创建一个这样的字典:

Dictionary<string, MyClass> dic = new Dictionary<string, MyClass>();

dic.add("z1", val1);
dic.add("abc9", val2);
dic.add("abc8", val3);
dic.add("ABC1", val4);

所以当我这样做时:

foreach (KeyValuePair<string, MyClass> kvp in dic)
{
}

我是否保证按如下方式检索这些值:“z1”、“abc9”、“abc8”、“ABC1”?

如果我首先这样做,会是:“z1”、“abc8”、“ABC1”吗?

dic.Remove("abc9");

【问题讨论】:

  • Am I guaranteed to have these values retrieved as such: "z1", "abc9", "abc8", "ABC1"?
  • 不,虽然可能会令人困惑,因为字典 IRL 当然是按字母顺序排列的 :)
  • @KierenJohnstone:除了表意语言。 . . :)
  • 尝试它并不能回答该功能是否被正式支持(因此将来仍会支持)。考虑到今天的实施只能伪造,不能验证。

标签: c# .net dictionary


【解决方案1】:

没有。来自MSDN(强调我的)

出于枚举的目的,字典中的每个项目都被视为 一个KeyValuePair&lt;TKey, TValue&gt; 结构,表示一个值及其 钥匙。 物品返回的顺序未定义

如果您想更好地控制迭代顺序,您可能需要查看 OrderedDictionary 类。

【讨论】:

    【解决方案2】:

    简短的回答是Dictionary&lt;TKey, TValue&gt; 不保证订单,您也不应指望订单得到维护。

    您可能想改用check into OrderedDictionary

    例子:

    OrderedDictionary d = new OrderedDictionary();
    
    d.Add("01", "First");
    d.Add("02", "Second");
    d.Add("03", "Third");
    d.Add("04", "Fourth");
    d.Add("05", "Fifth");
    
    for(int i = 0; i < d.Count; i++) // Print values in order
    {
       Console.WriteLine(d[i]);
    }
    

    请注意,由于某些奇怪的原因,没有通用的 OrderedDictionary&lt;TKey,TValue&gt; 版本。但是,this question 提供了一些关于如何实现的提示。

    【讨论】:

    • 谢谢。很好,我先问了。 OrderedDictionary 似乎是我需要的。所以你的意思是,如果我在上面的代码中将Dictionary 替换为OrderedDictionary,我的假设会成立,是吗?
    • @ahmd0 - 正确,但是由于某种原因,似乎不是OrderedDictionary 的通用版本,因此您必须在使用时转换每个值访问它们。
    • 不,不一样。刚刚验证过了。我上面显示的foreach 循环编译但随后以OrderedDictionary 而不是Dictionary 崩溃。必须更改为foreach (DictionaryEntry de in dic){}。就像你指出的那样,这些演员阵容也很烦人......
    • @ahmd0 - 是的,也许最好编写自己的实现。或者,Jon Skeet 建议使用 Dictionary&lt;&gt; 加上 List&lt;&gt; 来跟踪订单。
    【解决方案3】:

    我是否保证按如下方式检索这些值:“z1”、“abc9”、“abc8”、“ABC1”?

    绝对不是。始终将Dictionary&lt;,&gt; 视为键/值对的无序 集合。即使作为实现细节,如果您只添加值,您通常会以插入顺序看到它们,但您不应该依赖它。

    来自documentation

    出于枚举的目的,字典中的每个项目都被视为一个KeyValuePair&lt;TKey, TValue&gt; 结构,表示一个值及其键。 项目返回的顺序未定义。

    (强调我的。)

    如果您需要特定的订单,您应该使用不同的集合 - 如果您需要能够按键获取,则可能与字典结合使用。 (例如,维护 IList&lt;TKey&gt;Dictionary&lt;TKey, TValue&gt; 并不少见。)

    【讨论】:

    • 乔恩;如果您从不删除或操作字典,只添加项目,则底层实现似乎表明它们是有序的,因为它是一个条目数组。那会是正确的吗?我之前已经研究过这个问题并且无法打破这个前提!
    • @AllanElder:是的,这就是 current 实现所做的。但你永远不应该依赖它。
    • @AllanElder - 许多错误是假设行为永远不会改变的结果。如果不能保证排序顺序,则不能保证排序顺序。据我们所知,.NET 6.0 或 .NET 12.0 可能会完全重写 Dictionary&lt;&gt;,从而导致未来几年编写不佳的代码不兼容。到那时,原作者可能早就不在了,留下一些可怜的家伙来收拾烂摊子(是的,我就是那个可怜的家伙)。
    • @MikeChristensen:虽然有些人可能认为 .NET 已经有太多集合,但我希望看到 .NET 包含更多“仅添加”集合,因为这样的集合通常可以——最小的附加成本——在允许更多变化的集合中提供昂贵的保证。例如,在没有删除任何内容的字典中维护插入顺序很便宜;在存在删除的情况下维护它不是。仅添加集合中的线程安全性也比允许其他突变的集合便宜得多。
    【解决方案4】:

    不,不保证元素顺序。此外,它可能会根据 IDictionary<...> 接口的实际实现而有所不同。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-11-28
      • 1970-01-01
      • 2018-10-29
      • 2021-12-25
      • 1970-01-01
      • 1970-01-01
      • 2017-09-27
      • 1970-01-01
      相关资源
      最近更新 更多