System.Collections.Generic.Dictionary for每个顺序
本文关键字:顺序 for Dictionary Collections Generic System | 更新日期: 2023-09-27 18:15:36
查看一些遍历Dictionary的代码,似乎代码依赖于使用foreach对键值进行升序访问。
MSDN文档声明"为了枚举的目的,字典中的每个项都被视为表示值及其键的KeyValuePair结构。".
然而,在执行过程中,代码确实以"正确"的顺序访问每个KeyValuePair。
我已经更新了代码以显式地对项目进行排序,但如果有人能解释为什么原始代码的行为与作者所期望的一样,我很感兴趣。
#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
随机和任意的实现细节。它是明确地不保证,不应该依赖。它可以在不同的。net框架和不同的实现(mono等)上表现不同。
我查看了当前的实现。字典内部使用两个数组:一个用于包含键、值和其他信息的条目,另一个(称为buckets
)使用哈希码作为索引,并包含条目数组中相应条目的索引。bucket info确实是无序和无序的,但是条目数组是有序的,也就是说,它保持条目按照添加到字典中的顺序。然而,这些条目是未排序的,也就是说,如果您以未排序的方式添加条目,它们将保持未排序。
当字典被枚举时,数组也被枚举。这解释了您所看到的顺序。
不要依赖这个行为。如果微软改变实现,它将来可能会改变。