我已经查看了很多stackoverflow问题和关于ToList和泛型约束,但我还没有找到解释"语法错误"在最后的回报中。为什么我必须明确cast
和public 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
答案 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>();
}