Кто в словаре <>.First()?
В чем смысл метода расширения.NET 3.5 Enumerable.First()
когда вы называете это на экземпляре Dictionary
коллекция?
Набор ключей определяет, какой элемент является первым, или он просто не определен?
5 ответов
Что ж, я считаю, что набор ключей будет определять, какой элемент будет первым, но не четко определенным (или легко предсказуемым) способом. Другими словами, не думайте, что он всегда будет работать одинаково - это так же небезопасно, как полагаться на реализацию хеш-кода, которая остается неизменной между запусками.
РЕДАКТИРОВАТЬ: Я считаю, что на самом деле порядок вставки имеет значение, в отличие от моих предыдущих идей. Тем не менее, это зависит от реализации (поэтому может легко измениться в следующей версии). Я считаю, что в текущей реализации первая добавленная запись будет первой возвращенной, если она не была удалена. Если первая добавленная запись удаляется, порядок нарушается - это не значит, что самая ранняя запись удаляется. Вот пример:
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" - показывают, что последняя добавленная запись заканчивается тем, что возвращается первой.
Однако я хотел бы еще раз подчеркнуть, что между версиями фреймворка все может измениться.
Если вам нужен первый элемент в словаре, лучше всего использовать SortedDictionary. Я думаю, что метод First() просто вернет первый элемент, который находится сверху, но не обязательно первый, который был добавлен.
Я искал некоторый код, который использовал цикл foreach для получения "первого" элемента в объекте словаря. Код предполагает, что это первый добавленный в словарь.
Первоначально я думал, что метод Dictionary.First() будет более эффективным. Но потом я понял, что само понятие того, что представляет собой предмет, может не иметь особого смысла в этом контексте.
SortedDictionary, который предложил Echilon, вероятно, имеет больше накладных расходов и намного больше функциональности, чем мне нужно. Я склоняюсь к тому, чтобы просто сохранить ключ первого добавленного элемента.
Упорядочение 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>
не имеет нулевого значения в качестве первого элемента!
Это всегда гарантировано для Keys
коллекция словаря или DataRowCollection
(мой основной вариант использования для LINQ), или для Where()
при запуске на одной из этих коллекций.
Но это не гарантировано для List<string>
или List<DataRow>
, Так что, безусловно, есть обстоятельства, в которых вы хотели бы подумать дважды, прежде чем использовать FirstOrDefault()
,
Я еще покопался и обнаружил, что MSDN предупреждает, что порядок значений и ключей в словаре не указан. Поэтому я считаю, что это означает, что First() не всегда может возвращать одно и то же значение, когда вы добавляете больше значений.