谁在词典。第一个()?
当您在Dictionary
集合的实例上调用它时,.NET 3.5扩展方法Enumerable.First()
的含义是什么?
这组键是确定哪个项是第一个,还是只是没有定义?
好吧,我相信一组密钥将决定哪个项目是第一个,但不是以明确定义(或易于预测)的方式。 换句话说,不要以为它总是以相同的方式工作 – 它依赖于哈希代码实现在运行之间保持相同而不安全。
编辑:我相信事实上,插入的顺序确实很重要,这与我之前的想法相反。 但是,这是特定于实现的(因此可以在下一版本中轻松更改)。 我相信,对于当前的实现,添加的第一个条目将是返回的第一个条目( 如果尚未删除)。 如果添加的第一个条目被删除,则排序被破坏 – 并不是最早的条目被删除。 这是一个例子:
using System; using System.Collections.Generic; class Test { static void Main(string[] args) { var dict = new Dictionary(); dict.Add(0, 0); dict.Add(1, 1); dict.Add(2, 2); dict.Remove(0); dict.Add(10, 10); foreach (var entry in dict) { Console.WriteLine(entry.Key); } Console.WriteLine("First key: " + dict.First().Key); } }
结果为10,1,2和“First key:10” – 表示最新添加的条目最终返回。
但是,我想再次强调一切都可以在框架版本之间发生变化。
如果您需要字典中的第一项,则最好使用SortedDictionary。 我认为First()方法只返回恰好位于顶部的第一个项目,但不一定是第一个添加的项目。
我正在查看一些使用foreach循环来获取字典对象中“第一”项的代码。 代码假定这是第一个添加到字典中的代码。
最初我认为Dictionary.First()方法会更有效。 但后来我意识到,在这种背景下,首先是什么项目的概念可能没什么意义。
Echilon建议的SortedDictionary可能比我需要的开销和function更多。 我倾向于只保存添加的第一个元素的键。
未指定实现Dictionary
的类中的Keys
集合的顺序。 所以你不知道First()
将返回什么值。
但无论如何都有理由使用First()
– 或者更具体地说,使用FirstOrDefault()
。 如果你有一个采用IEnumerable
参数的方法,并且你知道T是一个默认值为null, your method can use
的类型null, your method can use
FirstOrDefault()来测试对象以查看它是否为空。
为什么要这样做而不是使用Count()
? 利用延迟执行。 如果在生成器上调用FirstOrDefault()
,则生成器会生成一个结果并停止。 如果在生成器上调用Count()
,则生成器必须枚举到列表的末尾。
所以你可以写一个这样的函数:
bool ListIsEmpty(IEnumerable list) { return list.FirstOrDefault() == null; }
并像这样使用它:
if (!ListIsEmpty(dict.Keys)) { Console.WriteLine("Dictionary is not empty"); } if (!ListIsEmpty(dict.Keys.Where(x => x.Contains("foo")) { Console.WriteLine("Dictionary has at least one key containing 'foo'."); }
并且知道代码正在做必须做的最低限度才能做出这些决定。
编辑:
我应该指出上面代码的另一个假设是: IEnumerable
没有null作为它的第一个项目!
对于字典的Keys
集合,或DataRowCollection
(我的LINQ的主要用例),或者在其中一个集合上运行时的Where()
,始终保证这一点。
但是不能保证List
或List
。 因此,在使用FirstOrDefault()
之前,您肯定需要三思而后行。
我做了一些挖掘,发现MSDN警告说字典中的值和键的顺序是未指定的。 所以我认为这意味着First()可能并不总是返回与添加更多值相同的值。