Подтвердить что ты не робот

Кто в словаре <>. Первый()?

В чем смысл метода расширения .NET 3.5 Enumerable.First(), когда вы вызываете его в экземпляре коллекции Dictionary?

Определяет ли набор ключей какой элемент первым, или он просто не определен?

4b9b3361

Ответ 1

Ну, я считаю, что набор ключей определит, какой элемент первым, но не в четко определенном (или легко предсказать) способе. Другими словами, не предполагайте, что он всегда будет работать одинаково - он небезопасен, поскольку полагается на реализацию хеш-кода, оставаясь тем же самым между прогонами.

EDIT: Я считаю, что на самом деле упорядочение вставки имеет значение, вопреки моим предыдущим идеям. Однако это специфично для реализации (поэтому его можно легко изменить в следующей версии). Я считаю, что с текущей реализацией первая добавленная запись будет первой, если она не была удалена. Если первая добавленная запись удаляется, упорядочение прерывается - это не значит, что самая ранняя запись удалена. Вот пример:

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 и "Первый ключ: 10" - показывая, что последняя добавленная запись заканчивается тем, что возвращается первым.

Тем не менее, я хотел бы еще раз подчеркнуть, что все может измениться между версиями фреймворка.

Ответ 2

Если вам нужен первый элемент в словаре, лучше всего использовать SortedDictionary. Я бы подумал, что метод First() просто вернет первый элемент, который находится наверху, но не обязательно первый, который был добавлен.

Ответ 3

Я искал какой-то код, который использовал цикл foreach для получения "первого" элемента в объекте словаря. Код предполагает, что это первый, добавленный в словарь.

Первоначально я думал, что метод Dictionary.First() будет более эффективным. Но потом я понял, что все понятие о том, что является первым, может не иметь особого смысла в этом контексте.

The SortedDictionary, который, по словам Эчилона, вероятно, имеет больше накладных расходов и намного большую функциональность, чем мне нужно. Я наклоняюсь, чтобы просто сохранить ключ первого добавленного элемента.

Ответ 4

Заказ коллекции 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'.");
}

и знайте, что код выполняет минимальный минимум, который он должен выполнить для принятия этих решений.

Edit:

Я должен указать, что другое предположение, сделанное выше кодом: что IEnumerable<T> не имеет нуля в качестве своего первого элемента!

Это всегда гарантируется для коллекции Keys словаря или DataRowCollection (мой основной вариант использования для LINQ) или для Where() при запуске в одной из этих коллекций.

Но это не гарантируется для List<string> или List<DataRow>. Таким образом, есть определенные обстоятельства, в которых вы хотели бы подумать дважды, прежде чем использовать FirstOrDefault().

Ответ 5

Я сделал еще несколько копаний и обнаружил, что MSDN предупреждает, что порядок значений и ключей в словаре не указан. Поэтому я считаю, что это означает, что First() может не всегда возвращать то же значение, что и дополнительные значения.