SortedList и Linq
Я запутался после прочтения документации о том, что ожидать при использовании Linq с SortedList.
https://msdn.microsoft.com/en-us/library/ms132319(v=vs.110).aspx
Я предполагаю, что перечисление гарантированно будет отсортировано, а также получено по индексу, но как насчет значений и ключей? Все ли эти случаи безопасны?
var list = new SortedList<DateTime, object>();
//add entries here ...
var firstValue1 = list.Values[0];
var firstValue2 = list.First().Value;
var firstValue3 = list.Values.First();
var firstKey1 = list.Keys[list.Count-1];
var firstKey2 = list.First().Key;
var firstKey3 = list.Keys.First();
var sortedList = list.Where(x => x.Key > DateTime.Now)
.Select(x => x.Value);
3 ответа
Прочитайте документацию...
Из документации по свойству Значения:
"Порядок значений в
IList<T>
такой же, как порядок вSortedList<TKey, TValue>
".
Из документации на свойство Keys:
"Порядок ключей в
IList<T>
такой же, как порядок вSortedList<TKey, TValue>
".
Если вы посмотрите на исходный код Enumerable.cs, вы увидите, что перегрузка без предиката просто пытается обработать источник как IList, и если это не работает, он возвращает первый элемент, используя перечислитель. И индекс, и перечислитель должны обрабатываться внутренне классом SortedList, так что вы получите соответствующий (отсортированный) результат:
public static TSource First<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
IList<TSource> list = source as IList<TSource>;
if (list != null) {
if (list.Count > 0) return list[0];
}
else {
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) return e.Current;
}
}
throw Error.NoElements();
}
Перегрузка с помощью предиката работает немного иначе, так как он выполняет предикат для каждого элемента с помощью перечислителя, ища первое совпадение:
public static TSource First<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
if (source == null) throw Error.ArgumentNull("source");
if (predicate == null) throw Error.ArgumentNull("predicate");
foreach (TSource element in source) {
if (predicate(element)) return element;
}
throw Error.NoMatch();
}
В любом случае, вы должны получить тот же (отсортированный) результат.
Вы можете проверить исходный код здесь:
По-видимому, Keys
Свойство - это просто оболочка вокруг экземпляра этого класса:
Если вы посмотрите на GetEnumerator()
метод, вы можете увидеть, что это создает SortedListKeyEnumerator
, Вот исходный код для этого:
Насколько я могу судить, MoveNext()
это просто перебирает ключи от SortedList
,
Вы можете узнать так же, как Values
работает.