21

当您在集合Enumerable.First()的实例上调用 .NET 3.5 扩展方法时,它的含义是什么?Dictionary

这组键是确定哪个项目是第一个,还是只是没有定义?

4

5 回答 5

17

好吧,我相信这组键确定哪个项目是第一个,但不是以明确定义(或易于预测)的方式。换句话说,不要假设它总是以相同的方式工作 - 它与依赖哈希码实现在运行之间保持相同一样不安全。

编辑:我相信事实上,插入的顺序确实很重要,这与我之前的想法相反。但是,这特定于实现的(因此可以在下一个版本中轻松更改)。我相信在当前的实现中,如果没有删除,添加的第一个条目将是第一个返回的条目。如果删除了添加的第一个条目,则顺序被破坏 - 并不是最早的条目被删除。这是一个例子:

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” - 表明最后添加的条目最先返回。

但是,我想再次强调,框架版本之间的一切都可能发生变化。

于 2009-01-12T20:47:01.800 回答
2

如果您需要字典中的第一项,最好使用 SortedDictionary。我认为 First() 方法只会返回恰好位于顶部的第一个项目,但不一定是添加的第一个项目。

于 2009-01-12T21:06:16.880 回答
2

我正在查看一些使用 foreach 循环来获取字典对象中的“第一个”项目的代码。该代码假定这是添加到字典中的第一个。

最初我认为 Dictionary.First() 方法会更有效。但后来我意识到,在这种情况下,首先是什么项目的整个概念可能没有多大意义。

Echilon 建议的 SortedDictionary 可能具有比我需要的更多的开销和更多的功能。我倾向于只保存添加的第一个元素的键。

于 2009-01-12T21:23:14.957 回答
0

我做了更多的挖掘,发现MSDN警告说字典中的值和键的顺序是未指定的。所以我相信这意味着 First() 在添加更多值时可能并不总是返回相同的值。

于 2009-01-12T23:19:18.560 回答
0

未指定Keys实现类中集合的顺序。Dictionary<TKey, TValue>所以你不知道First()会返回什么值。

但是First()无论如何都要使用 - 或者更具体地说,使用FirstOrDefault(). 如果您有一个带IEnumerable<T>参数的方法,并且您知道 T 是一个默认值为null, your method can useFirstOrDefault() 的类型,则可以测试对象是否为空。

你为什么要这样做而不是使用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().

于 2009-01-13T01:13:30.453 回答