Reputation: 19690
UPDATE: The following code only makes sense in C#4.0 (Visual Studio 2010)
It seems like I am having some misunderstanding of covariance/contravariance thing. Can anybody tell me why the following code doesn't compile?
public class TestOne<TBase>
{
public IEnumerable<TBase> Method<TDerived>(IEnumerable<TDerived> values)
where TDerived: TBase
{
return values;
}
}
while this one compiles: (!!!)
public interface IBase
{
}
public interface IDerived: IBase
{
}
public class TestTwo
{
public IEnumerable<IBase> Method(IEnumerable<IDerived> values)
{
return values;
}
}
Upvotes: 13
Views: 246
Reputation: 9335
I cannot think of any situation where you actually need TDerived
. Using TBase
is sufficient:
public class TestOne<TBase>
{
public IEnumerable<TBase> Method(IEnumerable<TBase> values)
{
return values;
}
}
After all, you have no information about TDerived
apart from the fact that it is a TBase
...
Upvotes: 1
Reputation: 1500435
Covariance only applies to reference types (for the type arguments), so you have to add a class constraint:
public IEnumerable<TBase> Method<TDerived>(IEnumerable<TDerived> values)
where TDerived : class, TBase
{
return values;
}
This will prevent you from trying to convert, say, an IEnumerable<int>
into an IEnumerable<object>
, which is invalid.
Upvotes: 13
Reputation: 1507
Neither compiled for me initially. Both failed on the implicit cast from Super(T/I) to Base(T/I). When I added an explicit case, however, both compiled.
public IEnumerable<TBase> Method<TSuper>(IEnumerable<TSuper> values)
where TSuper: TBase
{
return (IEnumerable<TBase>) values;
}
Upvotes: 0