【问题标题】:Is it possible to convert the result of the LINQ "Take" extension method to the original type?是否可以将 LINQ“Take”扩展方法的结果转换为原始类型?
【发布时间】:2019-04-18 11:19:38
【问题描述】:

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

从我得到的运行时错误来看,Take 方法的结果是 EnumerablePartition,它不能转换为 SortedList<int, int>

console App中的Main方法编译OK,但是在将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&lt;int, int&gt;,或者至少可以转换为SortedList&lt;int, int&gt;,因为这是原始类型。

这是我得到的运行时错误:

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 和泛型比较陌生,但由于提供了出色的答案,我创建了一种新的扩展方法以提高可读性:

    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


    【解决方案1】:

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

    嗯,它并不完全那样工作。如果您从一袋糖果中Take(2),则您有两个糖果。你不会因为原来的糖果装在一个袋子里而神奇地拥有一个装有两个糖果的新袋子。

    从技术上讲,Take 方法接受任何类型的 IEnumerable&lt;&gt; 并返回相同类型的 IEnumerable&lt;&gt;。原来容器类型的信息在这个过程中丢失了。

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

    【讨论】:

    • 这是我必须选择的IEnumerable&lt;&gt; 扩展方法的一个很好的类比。谢谢。
    【解决方案2】:

    你可以使用SortedListconstructor

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

    【讨论】:

      【解决方案3】:

      鉴于这是原始类型

      是的,但是Take()IEnumerable&lt;T&gt; 的扩展方法,SortedList&lt;TKey, TValue&gt; 实现了IEnumerable&lt;KeyValuePair&lt;TKey, TValue&gt;&gt;

      因此,您从 Take() 返回的类型不必与您调用它的源有任何关系 - 它仅返回 IEnumerable&lt;T&gt; 的实现,其中 TT 的类型相同IEnumerable&lt;T&gt; 中的一个。

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

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

      【讨论】:

        【解决方案4】:

        Take 不会返回 SortedList,因此您需要以一种或另一种方式创建一个新的:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-04-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多