C#中针对IEnumerable的泛型约束

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);
}

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

1
英语伙计。看不懂俄语。用谷歌翻译。http://translate.google.com/ - Nikhil Agrawal
Please translate the question text into English :) - Sergey Kalinichenko
2个回答

14
问题在于通用的协变仅适用于引用类型。例如,List<int> 不是 IEnumerable<Comparable>,但 List<string> 是。

因此,如果将 T 约束为引用类型,则可以编译:
public void Foo<T, I>() where T : class, I 
{
    IEnumerable<T> t = new List<T>();
    new List<I>().AddRange(t);
}

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接