3

If I apply the LINQ Take extension method to a SortedList<int, int>, how do I convert the result to a new SortedList<int, int>?

From the runtime error I'm getting, the result of the Take method is an EnumerablePartition which cannot be cast to SortedList<int, int>

Main method in console App compiles OK, but throws an error at runtime when casting the result of list.Take(2) to SortedList

        static void Main(string[] args)
        {
            Console.WriteLine("List");

            var list = new SortedList<int, int>();

            list.Add(2, 10);
            list.Add(8, 9);
            list.Add(3, 15);

            foreach (KeyValuePair<int, int> item in list){
                Console.WriteLine(item.Value);
            };

            Console.WriteLine("Short List");

            var shortlist = (SortedList<int, int>)list.Take(2);

            foreach (KeyValuePair<int, int> item in shortlist)
            {
                Console.WriteLine(item.Value);
            };

            Console.Read();

        }

I would have expected the result of the Take method to be a new SortedList<int, int> or at least that it would be possible to cast to a SortedList<int, int> given that this is the original type.

Here's the runtime error I'm getting:

Unable to cast object of type 'EnumerablePartition`1[System.Collections.Generic.KeyValuePair`2[System.Int32,System.Int32]]' to type 'System.Collections.Generic.SortedList`2[System.Int32,System.Int32]'

EDIT:

I'm relatively new to LINQ and Generics, but thanks to excellent answers provided, I've created a new extension method for readability:

    static class Extensions {

        public static SortedList<TKey, TValue> ToSortedList<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> collection)
        {
            var dictionary = collection.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
            return new SortedList<TKey, TValue>(dictionary);
        }
    }

Now, to create my shortlist:

var shortlist = list.Take(2).ToSortedList();

I was thinking that something like the above might already be available!

1

given that this is the original type

Yes, but Take() is an extension method on IEnumerable<T>, and SortedList<TKey, TValue> implements IEnumerable<KeyValuePair<TKey, TValue>>.

So the type you get back from Take() doesn't have to have any relation to the source you call it on - it merely returns an implementation of IEnumerable<T> where T is the same type as T of the IEnumerable<T> you call it on.

Instead instantiate a new list using the partition and its appropriate constructor:

var shortlist = new SortedList<int, int>(list.Take(2).ToDictionary(kvp => kvp.Key, kvp => kvp.Value));
8

I would have expected the result of the Take method to be a new SortedList or at least that it would be possible to cast to a SortedList given that this is the original type.

Well, it does not quite work that way. If you Take(2) from a bag of sweets, you have two sweets. You don't magically have a new bag with two sweets in it just because the original sweets came in a bag.

Technically speaking, the Take method takes an IEnumerable<> of any type and returns an IEnumerable<> of the same type. The information of the original container type is lost in the process.

Now obviously, as in our sweets example, if you want to have tiny bags of two sweets each from your big bag, there is no one stopping you from repackaging them. Same here. If you need a sorted list, create a new sorted list from the result. But that's manual.

  • This is a great analogy for the IEnumerable<> extension methods that I will have to co-opt. Thanks. – Andrew Hanlon Apr 22 at 18:35
2

You can use SortedList constructor

var sortedList = new SortedList<int, int>(list.Take(2).ToDictionary(x => x.Key, x => x.Value));
1

Take doesn't return a SortedList so you need to create a new one one way or another:

var shortList = new SortedList<int, int>();
foreach (var x in list.Take(2))
   shortList.Add(x.Key, x.Value);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.