鉴于以下内容:
class Base<T> {/*...*/}
class Der<T>: Base<T> {/*...*/}
interface Sth<T>{
IEnumerable<Base<T>> Foo {get;}
}
// and implementation...
class Impl<T>: Sth<T> {
public IEnumerable<Base<T>> Foo {
get {
return new List<Der<T>>();
}
}
}
如何编译?显然,该错误不是从List&lt; Der&lt; T&gt;&gt;中找到的隐式转换。列出&lt; Base&lt; T&gt;&gt;。如果我显式地转换它会发生InvalidCastException。
答案 0 :(得分:6)
从.NET Framework 3.5版开始,不支持您尝试进行的转换。由于添加了generic covariance/contravariance,它将在4.0版(Visual Studio 2010)中得到支持。虽然这仍然不允许您将List<Der>
投射到List<Base>
,但将允许您将IEnumerator<Der>
(列表实现的)投射到IEnumerator<Base>
}。
与此同时,您可以编写自己的实现IEnumerable<Base>
的类,并返回一个自定义IEnumerator<Base>
,它只包含List<Der>
的{{1}}。或者,如果您使用的是.NET Framework 3.5版,则可以像其他人所建议的那样使用Cast extension method。
答案 1 :(得分:4)
List<Der<T>>
无法转换为List<Base<T>>
,因为后者可以添加Base<T>
而前者不能。{/ p>
您可以使用Cast扩展程序方法解决此问题:return new List<Der<T>>().Cast<Base<T>>();
答案 2 :(得分:1)
让它编译......
class Impl<T> : Sth<T>
{
public IEnumerable<Base<T>> Foo
{
get
{
return new List<Base<T>>(); //change the List type to Base here
}
}
}
你总是可以这样做,这将从Der的实现中返回Base类的IEnumerable
class Impl<T> : Sth<T>
{
public IEnumerable<Base<T>> Foo
{
get
{
List<Der<T>> x = new List<Der<T>>();
foreach (Der<T> dt in x)
{
yield return dt;
}
}
}
}
答案 3 :(得分:1)
您可以使用以下命令使用LINQ从List<Der<T>>
投射到IEnumerable<Base<T>>,
:
class Impl<T>: Sth<T>
{
public IEnumerable<Base<T>> Foo
{
get
{
return new List<Der<T>>().Cast<Base<T>>();
}
}
}
正如其他答案所述,v3.5不支持通用转发,但您可以使用LINQ创建一个实现IEnumerable<Base<T>>.
的包装器对象
答案 4 :(得分:0)
这些答案帮助了我,我只想发布我的解决方案以解决我遇到的类似问题。
我为IEnumerable编写了一个扩展方法,只要我想转换List&lt; Foo&gt;,就会自动转换TSource。到IEnumerable&lt; Bar&gt; (我还在3.5)。
public static SpecStatus Evaluate<TSource, TSpecSource>(this IEnumerable<TSource> source, ISpec<IEnumerable<TSpecSource>> spec)
where TSource : TSpecSource
{
return spec.Evaluate(source.Cast<TSpecSource>());
}