我想我一定会丢失一些东西,为什么我不能编译它:

class Foo<T> where T : Bar
{
    T Bar;
}

abstract class Bar
{ }

class MyBar : Bar
{ }

static void Main(string[] args)
{
    var fooMyBar = new Foo<MyBar>();
    AddMoreFoos(fooMyBar);
}

static void AddMoreFoos<T>(Foo<T> FooToAdd) where T : Bar
{
    var listOfFoos = new List<Foo<Bar>>();
    listOfFoos.Add(FooToAdd); //Doesn't compile
    listOfFoos.Add((Foo<Bar>)FooToAdd); //doesn't compile
}

最佳答案

通过在此处使用列表,您会使事情比需要的事情更加困惑……最容易以这种方式查看效果:

// This won't compile
Foo<Bar> fooBar = new Foo<MyBar>();

鉴于此代码无法编译,因此您无法在Foo<MyBar>中添加List<Foo<Bar>>也就不足为奇了

那么,为什么Foo<MyBar>不是Foo<Bar>?因为泛型类不是协变的。

通用方差仅在C#4中引入-它仅适用于接口(interface)和委托(delegate)。因此,您可以(在C#4中)执行以下操作:
IEnumerable<MyBar> x = new List<MyBar>();
IEnumerable<Bar> y = x;

但是你做不到:
IList<MyBar> x = new List<MyBar>();
IList<Bar> y = x;

我有一个完整的讨论方差,您可以从NDC 2010 video site下载-只需搜索“方差”即可。

09-07 01:34