C# 谁在 Dictionary<>.First() 上?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/436954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 03:21:32  来源:igfitidea点击:

Who's on Dictionary<>.First()?

c#.net

提问by Larry Fix

What is the meaning of the .NET 3.5 extension method Enumerable.First()when you call it on an instance of the Dictionarycollection?

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

Does the set of keys determine which item is first, or is it just not defined?

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

采纳答案by Jon Skeet

Well, I believe the set of keys willdetermine which item is first, but not in a well-defined (or easy to predict) way. In other words, don't assume that it will always work the same way - it's as unsafe as relying on a hash code implementation staying the same between runs.

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

EDIT: I believe that in fact, the ordering of insertion doesmatter, contrary to my previous ideas. However, this isimplementation-specific (so could easily change in the next version). I believe that with the current implementation, the first entry added will be the first one returned ifit hasn't been removed. If the first entry added is ever removed, the ordering is broken - it's not that the earliestentry is removed. Here's an example:

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

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);
    }
}

The results are 10, 1, 2, and "First key: 10" - showing that the latestadded entry ends up being returned first.

结果是 10, 1, 2 和“First key: 10” - 表明最后添加的条目最先返回。

However, I'd like to stress again that everything can change between versions of the framework.

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

回答by Echilon

If you need the first item in a dictionary, you're best using a SortedDictionary. I would think the First() method will just return the first item which happens to be at the top, but not necessarily the first one that was added.

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

回答by Larry Fix

I was looking at some code that used a foreach loop to get the "first" item in a dictionary object. The code assumes that this is the first one added to the dictionary.

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

Initially I thought the Dictionary.First() method would be more efficient. But then I realized that the whole notion of what item is first might not make much sense in this context.

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

The SortedDictionary, which Echilon suggested, probably has more overhead and way more functionality than I need. I am leaning toward just save the key of the first element added.

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

回答by Larry Fix

I did some more digging and found that MSDNwarns that the order of values and keys in a Dictionary is unspecified. So I believe that means that First() may not always return the same value as you add more values.

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

回答by Robert Rossney

The ordering of the Keyscollection in a class implementing Dictionary<TKey, TValue>is not specified. So you don't know what value First()is going to return.

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

But there's a reason to use First()anyway - or, more specifically, to use FirstOrDefault(). If you have a method that takes an IEnumerable<T>argument, and you know T is a type whose default value is null, your method can useFirstOrDefault()` to test the object to see if it's empty.

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

Why would you do this instead of using Count()? To take advantage of deferred execution. If you call FirstOrDefault()on a generator, the generator yields one result and stops. If you call Count()on a generator, the generator has to enumerate to the end of the list.

你为什么要这样做而不是使用Count()?利用延迟执行。如果您调用FirstOrDefault()生成器,生成器会产生一个结果并停止。如果您调用Count()生成器,则生成器必须枚举到列表的末尾。

So you can write a function like this:

所以你可以写一个这样的函数:

bool ListIsEmpty(IEnumerable<string> list)
{
    return list.FirstOrDefault() == null;
}

and use it like this:

并像这样使用它:

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'.");
}

and know that the code is doing the bare minimum that it has to do in order to make those decisions.

并且知道代码正在做它为了做出这些决定而必须做的最低限度的工作。

Edit:

编辑:

I should point out that another assumption the code above is making: that the IEnumerable<T>doesn't have a null as its first item!

我应该指出上面的代码所做的另一个假设:IEnumerable<T>没有作为它的第一项的空值!

This is always guaranteed for the Keyscollection of a dictionary, or a DataRowCollection(my primary use case for LINQ), or for Where()when run on one of those collections.

这对于Keys字典的集合或DataRowCollection(我的 LINQ 的主要用例)或Where()在这些集合之一上运行时总是有保证的。

But it's not guaranteed for a List<string>or a List<DataRow>. So there are definitely circumstances in which you'd want to think twice before using FirstOrDefault().

但不能保证 aList<string>或 a List<DataRow>。因此,在某些情况下,您肯定会在使用FirstOrDefault().