Reputation: 171
public interface I {
}
public class A : I {
}
The compiler takes explicit IEnumerable<A>
as IEnumerable<I>
:
public void Test() {
IEnumerable<A> a = new List<A>();
new List<I>().AddRange(a);
}
But with generic constraints, we get:
public void Test<T>() where T : I {
IEnumerable<T> t = new List<T>();
new List<I>().AddRange(t);
}
^^^
Argument 1: cannot convert from 'IEnumerable<T>' to 'IEnumerable<I>'
However, this compiles fine.
public void Test<T>(T t) where T : I {
new List<I>().Add(t);
}
Hence the question: is this a correct behavior, or is it a bug?
Upvotes: 8
Views: 2100
Reputation: 56893
This has to do with Covariance and Contravariance. Suffice to say it is not a bug, but a feature.
For an indepth look at this I recommend Eric Lippert's blog post series here:
Upvotes: 1
Reputation: 1502935
The problem is that generic covariance only applies for reference types. For example, a List<int>
is not* an IEnumerable<Comparable>
, but a List<string>
is.
So if you constrain T
to be a reference type, it compiles:
public void Foo<T, I>() where T : class, I
{
IEnumerable<T> t = new List<T>();
new List<I>().AddRange(t);
}
Upvotes: 14