8
public interface I {
}
public class A : I {
}

编译器将显式IEnumerable<A>视为IEnumerable<I>

public void Test() {
    IEnumerable<A> a = new List<A>();
    new List<I>().AddRange(a);
}

但是有了通用约束,我们得到:

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>'

但是,这编译得很好。

public void Test<T>(T t) where T : I {
    new List<I>().Add(t);
}

因此问题是:这是一个正确的行为,还是一个错误?

4

2 回答 2

14

问题是泛型协方差仅适用于引用类型。例如, aList<int>不是* an IEnumerable<Comparable>,但 aList<string>是。

因此,如果您限制T为引用类型,它将编译:

public void Foo<T, I>() where T : class, I 
{
    IEnumerable<T> t = new List<T>();
    new List<I>().AddRange(t);
}
于 2012-07-24T12:22:21.680 回答
1

这与协方差和逆变有关。可以说这不是一个错误,而是一个功能。

为了深入了解这个,我推荐 Eric Lippert 的博客文章系列:

http://blogs.msdn.com/b/ericlippert/archive/2007/10/16/covariance-and-contravariance-in-c-part-one.aspx

于 2012-07-24T12:26:14.273 回答