是否可以将LINQ“Take”扩展方法的结果转换为原始类型?

问题描述 投票:3回答:4

如果我将LINQ Take扩展方法应用于SortedList<int, int>,如何将结果转换为新的SortedList<int, int>

从我得到的运行时错误,Take方法的结果是一个EnumerablePartition,无法强制转换为SortedList<int, int>

控制台App中的主要方法编译好,但在转换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();

我以为上面的东西可能已经可用了!

c# .net linq sortedlist
4个回答
1
投票

鉴于这是原始类型

是的,但是Take()IEnumerable<T>的扩展方法,而SortedList<TKey, TValue>实现了IEnumerable<KeyValuePair<TKey, TValue>>

因此,从Take()返回的类型不必与您调用它的源有任何关系 - 它只返回IEnumerable<T>的实现,其中T与您调用它的TIEnumerable<T>相同。

而是使用分区及其appropriate constructor实例化新列表:

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

8
投票

我希望Take方法的结果是一个新的SortedList,或者至少可以在给定这是原始类型的情况下转换为SortedList。

嗯,这种方式不太合适。如果你从一袋糖果中加入Take(2),你就会有两个糖果。你不会神奇地拥有一个装有两个糖果的新包,因为原来的糖果装在一个袋子里。

从技术上讲,Take方法采用任何类型的IEnumerable<>并返回相同类型的IEnumerable<>。原始容器类型的信息在此过程中丢失。

很明显,就像在我们的糖果示例中一样,如果你想从你的大包里拿出两个小糖果的小袋子,没有人阻止你重新包装它们。同样在这里。如果需要排序列表,请从结果中创建新的排序列表。但这是手册。


2
投票

你可以使用SortedList constructor

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);
© www.soinside.com 2019 - 2024. All rights reserved.