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>は *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

これは共変性と反変性と関係があります。これはバグではなく、機能であると言えば十分です。

これを詳しく見るには、EricLippertのブログ投稿シリーズをここでお勧めします。

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

于 2012-07-24T12:26:14.273 に答える