Stig
Stig

Reputation: 2086

SortedList and Linq

I'm confused after reading the documentation on what to expect when using Linq with a SortedList.

https://msdn.microsoft.com/en-us/library/ms132319(v=vs.110).aspx

I guess the enumeration is guaranteed to be sorted and also retrieve by index, but what about Values and Keys? Are all these cases safe?

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

Upvotes: 0

Views: 1503

Answers (3)

JuanR
JuanR

Reputation: 7783

If you look at the source code of Enumerable.cs, you will see that the overload without a predicate simply tries to treat the source as an IList and if that doesn't work, it returns the first element using the enumerator. Both the index and the enumerator are supposed to be handled internally by the SortedList class so that you get the appropriate (sorted) result:

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

The overload with a predicate works slightly different in that it executes the predicate against every item using the enumerator, looking for the first match:

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

Either way, you should be getting the same (sorted) result.

Upvotes: 0

Akos Nagy
Akos Nagy

Reputation: 4350

You can check out the source code here:

https://referencesource.microsoft.com/#System/compmod/system/collections/generic/sortedlist.cs,de670561692e4a20

Apparently, the Keys property is just a wrapper around an instance of this class:

https://referencesource.microsoft.com/#System/compmod/system/collections/generic/sortedlist.cs,374aa21b960ae2e2

If you look at the GetEnumerator() method, you can see it creates a SortedListKeyEnumerator. Here's the source code for that:

https://referencesource.microsoft.com/#System/compmod/system/collections/generic/sortedlist.cs,a4492235f85c77d8

As far as I can tell, the MoveNext() of this just iterates through the keys of the contained SortedList.

You can find out the same way how Values works.

Upvotes: 0

Chris
Chris

Reputation: 27609

Read the documentation...

From the documentation on the Values property:

"The order of the values in the IList<T> is the same as the order in the SortedList<TKey, TValue>."

From the documentation on the Keys property:

"The order of the keys in the IList<T> is the same as the order in the SortedList<TKey, TValue>."

Upvotes: 2

Related Questions