简体   繁体   English

System.Collections.Generic.Dictionary foreach顺序

[英]System.Collections.Generic.Dictionary foreach order

Looking at some code that iterates through a Dictionary, and it appears that the code relies on access by ascending order of the key values, using foreach. 查看一些遍历Dictionary的代码,似乎该代码使用foreach通过键值的升序来依赖于访问。

The MSDN documentation states that " For purposes of enumeration, each item in the dictionary is treated as a KeyValuePair structure representing a value and its key. The order in which the items are returned is undefined. ". MSDN文档指出:“ 出于枚举目的,字典中的每个项目都被视为代表值及其键的KeyValuePair结构。未定义返回项目的顺序。 ”。

Yet during execution the code does access each KeyValuePair in the 'correct' order. 但是在执行期间,代码确实以“正确”顺序访问每个KeyValuePair。

I've updated the code to order the items explicitly, but was interested if anyone had an explanation as to why the original code behave as the author expected. 我已经更新了代码以明确地订购商品,但对于是否有人对原始代码为何表现出作者预期的解释感到关注。

#if pl
my $hdr = '
  Test script.
  Once per session, run
    "C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\vcvars32.bat"
   or equivalent.
  Run "perl FooInstallTest.cs".
';

use strict;
use Test::More tests => 2;
use sigtrap 'handler', \&cleanup, 'normal-signals';

my @reference = (qw(
));


sub main {
   my $ret;
   my $prog = "FooInstallTest.exe";

   my $cmd =
    "csc /debug " .
    "/nologo " .
    "/platform:x86 " .
    "/out:FooInstallTest.exe " .
    "/d:TRACE /d:DEBUG " .
    "/define:FooInstallTest " .
    ""
   ;

   foreach my $reference (@reference) {
      $cmd .= ('/reference:' . $reference . " ");
   }

   $cmd .=
    "FooInstallTest.cs " .
    "";

   unlink($prog);

   foreach my $reference (@reference) {
      system("xcopy /y $reference .");
   }

   1 && print("$cmd\n");
   $ret = system($cmd);
   is($ret, 0, "Compile.");

   my $run = $prog;
   1 && print("$run\n");
   $ret = system($run);
   is($ret, 0, "Run.");

   cleanup();
}

sub cleanup {
   foreach my $reference (@reference) {
      $reference =~ s/.*\\//;
      (-e $reference) && (unlink($reference));
   }
}

main();

__END__
#endif

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Data;
using System.Data.Linq;
using System.Diagnostics;
using System.Linq;

#if FooInstallTest
#endif


#if FooInstallTest
public class FooInstallTest {

   public static int Main(String[] args) {
      FooInstallTest foo_install_test = new FooInstallTest();
      return foo_install_test.main();
   }

   public int main() {
      UpdateFooDB();
      return 0;
   }

   void UpdateFooDB() {
      string serverPath = 
       @"Server=.\sqlexpress;Trusted_Connection=True;Database=foo;";

      System.Collections.Generic.Dictionary<double, string> upgrades = 
       new System.Collections.Generic.Dictionary<double, string> {
         {1.2,   "foo_1_2.sql"},
         {1.3,   "foo_1_3.sql"},
         {1.6,   "foo_1_6.sql"},
         {1.7,   "foo_1_7.sql"},
         {1.8,   "foo_1_8.sql"},
         {1.9,   "foo_1_9.sql"},
         {2.0,   "foo_2_0.sql"},
         {2.01,  "foo_2_01.sql"},
         {2.02,  "foo_2_02.sql"},
         {2.03,  "foo_2_03.sql"},
         {2.031, "foo_2_031.sql"},
         {2.032, "foo_2_032.sql"},
         {2.033, "foo_2_033.sql"},
         {2.034, "foo_2_034.sql"},
         {2.035, "foo_2_035.sql"},
         {2.036, "foo_2_036.sql"},
         {2.037, "foo_2_037.sql"},
         {2.038, "foo_2_038.sql"},
         {2.039, "foo_2_039.sql"},
         {2.040, "foo_2_040.sql"},
         {2.041, "foo_2_041.sql"},
         {2.042, "foo_2_042.sql"},
      };
      UpdateDatabase(serverPath, upgrades);
   }

   void UpdateDatabase(
    string serverPath, 
    System.Collections.Generic.Dictionary<double, string> upgrades
   ) {
      //ing (SqlConnection conn = new SqlConnection(serverPath))
      {
         //nn.Open();

         double targetVersion = upgrades.LastOrDefault().Key;
         //uble currentVersion = GetVersion(conn);
         double currentVersion = 1.0;

         string diagMessage = String.Format(
          "Installer: Update Database: current: [{0}], target: [{1}]"
          ,currentVersion.ToString()
          ,targetVersion.ToString()
         );
         Console.WriteLine(diagMessage);

         foreach (var item in upgrades) {
            if ((currentVersion < targetVersion) && (currentVersion < item.Key)) {
               diagMessage = String.Format(
                "Execute Update: current: [{0}], key: [{1}], file: [{2}]"
                ,currentVersion.ToString()
                ,item.Key.ToString()
                ,item.Value.ToString()
               );
               Console.WriteLine(diagMessage);
               //ecuteSqlFile(conn, item.Value);
               currentVersion = item.Key;
            }
         }
      }
   }
}

#endif

By chance and arbitrary implementation details. 偶然和任意实施的细节。 It is explicitly not guaranteed and should not be relied upon. 明确地不能保证也不应该依赖它。 It could behave differently on different .NET frameworks and different implementations (mono, etc). 在不同的.NET框架和不同的实现(单声道等)上,它的行为可能有所不同。

I looked at the current implementation. 我查看了当前的实现。 The dictionary uses two arrays internally: one for the entries containing the key, the value and other infos, and another (called buckets ) using the hash code as index and containing the indexes of the corresponding entries within the entries array. 字典在内部使用两个数组:一个用于包含键,值和其他信息的条目,另一个用于使用哈希码作为索引并在entrys数组中包含相应条目的索引的条目(称为buckets )。 The buckets info is indeed unsorted and unordered, but the entries array is ordered, ie it keeps the entries in the order they have been added to the dictionary. 存储桶信息的确是未排序且未排序的,但是entrys数组是有序的,即,它将条目按它们添加到字典的顺序保留。 These entries are however not sorted, ie if you add the entries in an unsorted way, they will remain unsorted. 但是,这些条目未排序,即,如果您以未排序的方式添加条目,则它们将保持未排序状态。

When the dictionary is enumerated the entries array is enumerated. 枚举字典时,枚举entrys数组。 This explains the order you have seen. 这说明了您看到的顺序。

Don't rely on this behavior. 不要依靠这种行为。 It could change in future, if Microsoft changes the implementation. 如果Microsoft更改实现,将来可能会更改。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 System.Collections.Generic.Dictionary =终极表现? - System.Collections.Generic.Dictionary = Ultimate performance? 将System.Collections.Generic.Dictionary转换为XDocument - Turn a System.Collections.Generic.Dictionary into an XDocument 反序列化 System.Collections.Generic.Dictionary - deserializing System.Collections.Generic.Dictionary &#39;System.Collections.Generic.Dictionary的最佳重载方法匹配 <int,System.Collections.Generic.Dictionary<string,int> &gt; .Dictionary(int)&#39; - The best overloaded method match for 'System.Collections.Generic.Dictionary<int,System.Collections.Generic.Dictionary<string,int>>.Dictionary(int)' 通过for语句循环通过System.Collections.Generic.Dictionary - Loop through System.Collections.Generic.Dictionary via for statement LINQ to Entities无法识别方法&#39;System.Collections.Generic.Dictionary` - LINQ to Entities does not recognize the method 'System.Collections.Generic.Dictionary` 如何在 Realm-dotnet 中存储 System.Collections.Generic.Dictionary - How to store a System.Collections.Generic.Dictionary in realm-dotnet 枚举System.Collections.Generic.Dictionary中的键<string,string> - enumerate keys in in a System.Collections.Generic.Dictionary<string,string> System.Collections.Generic.Dictionary`Add`vs set&#39;Item` - System.Collections.Generic.Dictionary `Add` vs set `Item` 无法将类型字符串隐式转换为System.Collections.Generic.Dictionary <string,System.Collections.Generic.Dictionary><string,object> &gt; - Cannot implicitly convert type string to System.Collections.Generic.Dictionary<string,System.Collections.Generic.Dictionary><string,object>>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM