Reputation: 6017
Given the following:
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>>();
}
}
}
How can I get this to compile? The error is, obviously, not implicit conversion found from List<Der<T>> to List<Base<T>>. If I cast it explicitly InvalidCastException occurs.
Upvotes: 5
Views: 2796
Reputation: 17584
These answers helped me out, and I just wanted to post my solution for a similar problem I had.
I wrote an extension method for IEnumerable that automatically casts TSource whenever I want to convert a List<Foo> to an IEnumerable<Bar> (I'm still on 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>());
}
Upvotes: 0
Reputation: 8941
The conversion you're trying to make isn't supported as of version 3.5 of the .NET Framework. It will be supported in version 4.0 (Visual Studio 2010) due to the addition of generic covariance/contravariance. While this will still not allow you to cast List<Der>
to List<Base>
, it will allow you to cast IEnumerator<Der>
(which the list implements) to IEnumerator<Base>
.
In the meantime, you can write your own class that implements IEnumerable<Base>
and returns a custom IEnumerator<Base>
that simply wraps List<Der>
's IEnumerator<Der>
. Alternatively, if you are using the .NET Framework version 3.5, you can use the Cast extension method, as others have suggested.
Upvotes: 6
Reputation: 2077
You can use LINQ to cast from List<Der<T>>
to an IEnumerable<Base<T>>,
by using:
class Impl<T>: Sth<T>
{
public IEnumerable<Base<T>> Foo
{
get
{
return new List<Der<T>>().Cast<Base<T>>();
}
}
}
As the other answers have stated, generic convariance is not supported in v3.5, but you can use LINQ to created a wrapper object that implements IEnumerable<Base<T>>.
Upvotes: 1
Reputation: 74802
List<Der<T>>
is not convertible to List<Base<T>>
because the latter can have a Base<T>
added to it and the former can't.
You can resolve this using the Cast extension method: return new List<Der<T>>().Cast<Base<T>>();
Upvotes: 4
Reputation: 12567
To make it compile...
class Impl<T> : Sth<T>
{
public IEnumerable<Base<T>> Foo
{
get
{
return new List<Base<T>>(); //change the List type to Base here
}
}
}
You could always do something like this too, which would return the IEnumerable of the Base class from an implementation of Der
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;
}
}
}
}
Upvotes: 1