当您在集合Enumerable.First()
的实例上调用 .NET 3.5 扩展方法时,它的含义是什么?Dictionary
这组键是确定哪个项目是第一个,还是只是没有定义?
好吧,我相信这组键将确定哪个项目是第一个,但不是以明确定义(或易于预测)的方式。换句话说,不要假设它总是以相同的方式工作 - 它与依赖哈希码实现在运行之间保持相同一样不安全。
编辑:我相信事实上,插入的顺序确实很重要,这与我之前的想法相反。但是,这是特定于实现的(因此可以在下一个版本中轻松更改)。我相信在当前的实现中,如果没有删除,添加的第一个条目将是第一个返回的条目。如果删除了添加的第一个条目,则顺序被破坏 - 并不是最早的条目被删除。这是一个例子:
using System;
using System.Collections.Generic;
class Test
{
static void Main(string[] args)
{
var dict = new Dictionary<int, int>();
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 可能具有比我需要的更多的开销和更多的功能。我倾向于只保存添加的第一个元素的键。
我做了更多的挖掘,发现MSDN警告说字典中的值和键的顺序是未指定的。所以我相信这意味着 First() 在添加更多值时可能并不总是返回相同的值。
未指定Keys
实现类中集合的顺序。Dictionary<TKey, TValue>
所以你不知道First()
会返回什么值。
但是First()
无论如何都要使用 - 或者更具体地说,使用FirstOrDefault()
. 如果您有一个带IEnumerable<T>
参数的方法,并且您知道 T 是一个默认值为null, your method can use
FirstOrDefault() 的类型,则可以测试对象是否为空。
你为什么要这样做而不是使用Count()
?利用延迟执行。如果您调用FirstOrDefault()
生成器,生成器会产生一个结果并停止。如果您调用Count()
生成器,则生成器必须枚举到列表的末尾。
所以你可以写一个这样的函数:
bool ListIsEmpty(IEnumerable<string> 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<T>
它的第一项没有 null!
Keys
对于字典的集合或DataRowCollection
(我对 LINQ 的主要用例)的集合,或者在其中一个集合上运行时,始终可以保证这一点Where()
。
但不能保证 aList<string>
或 a List<DataRow>
。因此,在某些情况下,您在使用FirstOrDefault()
.