使用LINQ ToList将GENERIC列表转换为其基类型列表的语法

时间:2017-12-27 23:03:37

标签: c# linq generics tolist

我已经查看了很多stackoverflow问题和关于ToList和泛型约束,但我还没有找到解释&#34;语法错误&#34;在最后的回报中。为什么我必须明确castpublic interface I1 { } public class C2 : I1 { public static List<I1> DowncastListA( List<C2> list ) { // "A": A concrete class works. return list == null ? null : list.ToList<I1>(); } public static List<I1> DowncastListB<T2>( List<T2> list ) where T2 : I1 { // "B": WORKS, if explicitly Select and Cast each element. return list == null ? null : list.Select( a => (I1)a ).ToList(); } public static List<I1> DowncastListC<T2>( List<T2> list ) where T2 : I1 { // "C": Syntax Error: 'List<T2>' does not contain a definition for 'ToList' and the best extension method overload 'ParallelEnumerable.ToList<I1>(ParallelQuery<I1>)' requires a receiver of type 'ParallelQuery<I1>' return list == null ? null : list.ToList<I1>(); } } 元素(&#34; B&#34;)?

{{1}}

一些相关的问题:
Raymond Chen's blog
https://stackoverflow.com/a/1541173/199364

2 个答案:

答案 0 :(得分:1)

扩展方法IEnumerable<T>.ToList<T>()不允许指定目标类型。 T是源IEnumerable的类型(从源集合中隐式知道)。

相反,你可以使用它:

public static List<I1> DowncastListC<T2>( List<T2> list ) where T2 : I1
{
    return list == null ? null : list.Cast<I1>().ToList();
}

即。首先投射每个元素(产生IEnumerable<I1>),然后从中创建一个列表。

顺便说一句:您甚至可以使用扩展方法来简化其用法:

public static class Extensions
{
    public static List<I1> Downcast<T2>(this List<T2> list) where T2 : I1
    {
        return list == null ? null : list.Cast<I1>().ToList();
    }
}

答案 1 :(得分:0)

正如@AluanHaddad所建议的

    public static IReadOnlyList<I1> DowncastList<T2>( List<T2> list ) where T2 : class, I1
    {
        return list;
    }

请注意添加的约束T2 : class 该答案不需要任何list的转换,因为IReadOnlyList<T>是协变的,而list已经有成员实现I1。 (或者可以使返回类型为IEnumerable<I1>,但我需要建立索引,因此选择公开更高的接口。)

或者作为替代方案,如果希望公开完整的List功能:

    public static List<I1> DowncastList<T2>( List<T2> list ) where T2 : class, I1
    {
        return list == null ? null : list.ToList<I1>();
    }

请注意添加的约束T2 : class。这为IEnumerable<T2>List<T2>实现)提供了足够的信息来查找ToList&lt;&gt;`的实现。

现在,这是有效的,这是上面的第二个版本,使用C#6 null conditional:

    public static List<I1> DowncastList<T2>( List<T2> list ) where T2 : class, I1
    {
        return list?.ToList<I1>();
    }