【问题标题】:OOC: What is the difference between ToList() and casting to List<T> in .NET?OOC:在 .NET 中 ToList() 和强制转换为 List<T> 有什么区别?
【发布时间】:2011-01-07 14:31:34
【问题描述】:

OOC:出于好奇

因此,作为一个小练习和学习的目的,我决定检查我是否能够实现一个非常基本的递归函数,该函数将返回 List&lt;int&gt;,但有以下限制:

1- 结果应该由函数本身返回(而不是作为参数传递给void 函数)。

2 - 函数体中没有声明局部“命名”变量。

我想出了下面的解决方案(顺便说一句:这可以通过任何方式改进吗?)

在执行此操作时,我了解到 ToList() 与投射到 List&lt;T&gt; 不同(请参见下面的示例) - 任何可以解释幕后发生的事情以及两者之间的区别是什么的人?

谢谢!

PS - 我使用的是 4.0 版(以防万一)。

编辑:运行时错误是Unable to cast object of type '&lt;ConcatIterator&gt;d__71'1[System.Int32]' to type 'System.Collections.Generic.List'1[System.Int32]'

public static List<int> SomeIntegers(int min, int max)
{
    //assume max >= min for simplicity  
    if (min == max)
        return new List<int>() { min };

    // runtime error 
    //return (List<int>)(SomeIntegers(min, max - 1).Concat(new List<int>() { max }));   

    //works
    return (SomeIntegers(min, max - 1).Concat(new List<int>() { max })).ToList(); 
}

【问题讨论】:

    标签: c# collections casting


    【解决方案1】:

    ToList() 与(强制转换)到 List 不同。

    ToList() 接受任何IEnumerable(列表、数组、字典、集合等)并将其转换为List

    转换为List 获取一个已经是某种列表的对象,并将其标记为列表。示例:

    // fail -- arrays are not lists
    var not_a_list = (List<int>)int[];
    // success: arrays *are* IEnumerable, so you can convert them to a list.
    var list_from_array = new [] { 1,2,3,4,5 }.ToList();
    // success: WorkflowRoleCollection derives from List<WorkflowRole>
    var derived_from_list = (List<WorkflowRole>) new WorkflowRoleCollection();
    

    在您的情况下,Concat() 返回 IEnumerable,而不是 List。请记住,它必须支持生成器(它们是惰性求值的),因此将其作为下面的列表是没有意义的。

    顺便说一句,你看过内置函数Enumerable.Range吗?

    【讨论】:

      【解决方案2】:
      • 只有当你实际上有一个List&lt;T&gt;、派生自List&lt;T&gt; 的东西,或者具有到List&lt;T&gt; 的有效类型转换的东西时,强制转换才有效,否则它会因InvalidCastException 而失败。 ToList() 适用于任何 IEnumerable。
      • ToList() 总是会创建一个新的列表副本,即使您已经有一个列表。将某些内容强制转换为 List&lt;T&gt; 通常不会生成列表的副本 - 它只会为您提供同一对象的新编译时类型。

      【讨论】:

        【解决方案3】:

        顺便说一句,生成整数列表的最佳方法是:

        Enumerable.Range(min, length);
        

        Enumerable.Range(min, max-min+1);
        

        但这并不能帮助你学习,所以向你致敬! :)

        【讨论】:

        • 谢谢,我刚刚检查了这个;所以似乎我们没有得到Enumerable.Range(min, max, step)Enumerable.Range(min, max, x =&gt; x*x),对吧?
        • 不是直接的,但你当然可以做类似Enumerable.Range(min, length).Where(x =&gt; (x-min)%step==0)Enumerable.Range(min, length).Select(x =&gt; x*x); 的操作来获得等价物
        • 还要注意 Enumerable.Range 的第二个参数是 LENGTH,而不是 MAX
        猜你喜欢
        • 2012-02-10
        • 2021-05-28
        • 1970-01-01
        • 2010-12-08
        • 1970-01-01
        • 2010-09-28
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多