【发布时间】:2020-07-16 05:55:42
【问题描述】:
已经提出了与以下类似的问题,具体参考了此处的字典:Does the Enumerator of a Dictionary<TKey, TValue> return key value pairs in the order they were added? 和此处:Dictionary enumeration order
阅读这些很明显,不应依赖字典枚举的顺序。根据字典枚举的不确定顺序,我最近观察到,当针对 .NET Core 3.1(在分支中)构建测试项目时,单元测试会间歇性地失败(在构建机器上)。相比之下,针对 .NET Framework 4.7.2(在不同的分支上)构建的同一测试项目没有失败。这些观察来自许多单独的单元测试执行。最终,我将失败追溯到数值运算(1/x 的总和),其中值(x)存储在一个以String 为键的 ImmutableDictionary 中。在单元测试的情况下,求和的顺序会影响结果。已对计算进行了修复:使用 ImmutableSortedDictionary。
此处是演示 ImmutableDictionary 中键的不同顺序的精简代码 sn-p(针对 .NET Core 3.1 编译并执行多次以观察不同的枚举):
static void Main(string[] args)
{
var dict = ImmutableDictionary<string,double>.Empty;
for (int i = 0; i < 10; i++)
{
dict = dict.Add(i.ToString(),i);
}
Console.WriteLine("Keys collection: " + string.Join(", ",dict.Keys.ToList()));
Console.WriteLine("Keys during enumeration: " +string.Join(", ", dict.Select(c => c.Key).ToList()));
}
但是,正如对有关Dictionary 的问题的回答中所述:“Dictionary 确实以相同的顺序返回项目(假设您没有触发哈希表的调整大小)”。同样,我知道不应依赖当前的排序行为,但不清楚在什么情况下(例如,使用 .NET Framework、.NET Standard、.NET Core 时)执行之间的排序实际上不同。我的问题是:
为什么 ImmutableDictionary(在 .NET Framework 4.7.2 中)在执行之间以相同的顺序返回项目,而 ImmutableDictionary(在 .NET Core 3.1 中)始终以不同的顺序返回项目?
【问题讨论】:
-
您真的想知道为什么吗?没有挖掘源代码并进行比较,我想最简单的答案是它们是不同的代码库。然而,除了行为之外,不应依赖其作为实现细节(如您所见)
-
每天我走进商店都会看到按字母顺序排列的巧克力棒。我问店主他保证每天都做吗?他说不。第二天去问他们为什么今天不正常有意义吗?不——因为他明确表示他没有承诺。 说顺序不是确定性的全部意义在于避免您依赖它。回答您所问问题的危险在于您将依赖实施细节可能会改变。
-
a Dictionary does return items in the same order (assuming that you don't trigger a resize of the hashtable)"更准确的说法是a Dictionary does currently return items in the same order (assuming that you don't trigger a resize of the hashtable) in the current implementations and runtimes, but that may change in future". -
They indicated that, despite enumeration order being "undefined", the order of enumeration is deterministic.你表现得好像这两个陈述相互矛盾。undefined不代表random。这意味着I promise nothing。您说订单是确定性的——订单具体不保证根据合同是确定性的。 如果您依赖订单,那么您做错了。合同明确规定“不要那样做”。 -
does anyone know which versions/platforms consistently return the same ordering between executions?简短的回答是 - 他们都没有承诺这样做。因此,任何测试都应该根据合同编写,而不是观察到的行为。Why does an ImmutableDictionary (in .NET Framework 4.7.2) return items in the same order between executions but an ImmutableDictionary (in .NET Core 3.1) consistently return items in a different order?因为合同没有说它不能这样做。如果它是无序的,那么根据定义,它可以存储/排序/返回它自己。