Можно ли преобразовать результат метода расширения LINQ «Take» в исходный тип?

2

Если я применяю метод расширения LINQ Take к SortedList<int, int>, как мне преобразовать результат в новый SortedList<int, int>?

Из полученной ошибки во время выполнения, результатом метода Take является EnumerablePartition который не может быть приведен к SortedList<int, int>

Основной метод в консольном приложении компилируется нормально, но выдает ошибку во время выполнения при приведении результата list.Take(2) к 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();

        }

Я ожидал, что результатом метода Take будет новый SortedList<int, int> или хотя бы то, что можно будет привести его к SortedList<int, int> учитывая, что это оригинальный тип.

Вот ошибка времени выполнения, которую я получаю:

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]'

РЕДАКТИРОВАТЬ:

Я относительно новичок в LINQ и Generics, но благодаря полученным отличным ответам я создал новый метод расширения для удобства чтения:

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

Теперь, чтобы создать мой список:

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

Я думал, что что-то подобное может быть уже доступно!

Теги:
linq
sortedlist

4 ответа

1
Лучший ответ

учитывая, что это оригинальный тип

Да, но Take() является методом расширения в IEnumerable<T>, а SortedList<TKey, TValue> реализует IEnumerable<KeyValuePair<TKey, TValue>>.

Таким образом, тип вы получаете назад от Take() не должен иметь никакого отношения к источнику вы называете его - она просто возвращает реализацию IEnumerable<T>, где T является тот же тип T от IEnumerable<T> Вы называете это.

Вместо этого создайте новый список, используя раздел и соответствующий ему конструктор:

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

Я ожидал бы, что результатом метода Take будет новый SortedList или, по крайней мере, будет возможно приведение к SortedList, учитывая, что это оригинальный тип.

Ну, это не совсем так. Если вы Take(2) из пакета конфет, у вас есть две конфеты. У вас нет волшебной сумки с двумя конфетами просто потому, что в сумке были оригинальные конфеты.

Технически говоря, метод Take принимает IEnumerable<> любого типа и возвращает IEnumerable<> того же типа. Информация исходного типа контейнера теряется в процессе.

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

  • 0
    Это отличная аналогия для методов расширения IEnumerable<> которые мне придется использовать. Благодарю.
2

Вы можете использовать конструктор SortedList

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

Take не возвращает SortedList поэтому вам нужно создать новый так или иначе:

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню