是Dictionary.Last()的返回值未定义
本文关键字:返回值 未定义 Dictionary Last | 更新日期: 2023-09-27 18:09:15
今天我在阅读的一些代码中遇到了Dictionary.Last()
的使用。对我来说,这是没有意义的,因为字典没有"最后"元素的明确概念。检查MSDN给了我以下信息:
为了枚举的目的,字典中的每个项都被视为表示值及其键的KeyValuePair结构。返回项的顺序未定义。
听起来好像Last()
的结果也是未定义的,但是该方法实际上并没有"按顺序返回项",它暗示它根据内部顺序返回项。我可能想多了,但这是有区别的。
使用以下代码进行我自己的测试,结果每次运行测试时都一致地返回"Fifteen"。
class Program
{
static void Main(string[] args)
{
Dictionary<int, string> dictionary = new Dictionary<int, string>();
dictionary.Add(10, "Ten");
dictionary.Add(5, "Five");
dictionary.Add(20, "Twenty");
dictionary.Add(2, "Two");
dictionary.Add(15, "Fifteen");
Console.WriteLine(dictionary.Last());
Console.ReadKey();
}
}
所以现在我想知道是否可以安全地假设Dictionary.Last()返回最后一个添加的值,或者如果不应该使用该方法,因为文档说返回项的顺序未定义,而没有明确说明Last()
的行为?
Dictionary.Last()
总是返回最后添加的项的假设很容易被证明是失败的,如下所示:
var dict = new Dictionary<Guid, Guid>();
Guid a = Guid.Empty, b = a, c = a, d = a;
for (int i = 0; i < 1000; ++i)
{
var guid = Guid.NewGuid();
dict.Add(guid, guid);
if (dict.Last().Key != guid)
Console.WriteLine("Failed at iteration " + i);
if (d != Guid.Empty)
dict.Remove(d);
d = c;
c = b;
b = a;
a = guid;
}
因此Enumerable.Last()
与Dictionary
一起使用的返回值是undefined
(对于Dictionary
的当前实现,看起来只要您删除了一个项,那么Last()
就不再返回最近添加的项。)
"我想知道假设Dictionary.Last()返回最后添加的值是否安全"
号项的返回顺序未定义
它们可能按照您现在需要的顺序,但未定义的行为可能会随着内部实现的更改而随时更改。
顺序本身是由Dictionary
内部定义的。因此,从当前实现来看,是确定性的,并且对于相同的输入返回相同的顺序-在您的情况下,Fifteen
将始终是最后一项。但是,由于实际顺序依赖于内部实现(可能依赖于键的哈希码),您不应该依赖于此顺序,因为它不太可能是您期望的。
特别是顺序是一个实现细节。如果你依赖于此,当微软决定更改内部代码(而不是API)时,你就会遇到问题。