繁体   English   中英

为什么不能将一个受约束的开放泛型类型转换为受约束类型?

[英]Why can't you cast a constrained open generic typed to the constrained type?

我想我一定遗漏了一些东西,为什么我不能编译这个:

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 中引入 - 它仅适用于接口和委托。 所以你可以(在 C# 4 中)这样做:

IEnumerable<MyBar> x = new List<MyBar>();
IEnumerable<Bar> y = x;

但你不能这样做:

IList<MyBar> x = new List<MyBar>();
IList<Bar> y = x;

我有一个完整的关于方差的讨论,您可以从NDC 2010 视频网站下载 - 只需搜索“方差”。

它无法编译,因为如果您要使用Foo<int>调用您的方法,那么该调用将失败:您正试图为泛型参数假定特定类型。

您需要使用var listOfFoos = new List<Foo<T>>()代替,然后Add应该可以工作。

(编辑:同样,如果您使用Foo<T> ,演员也会起作用 - 但您仍然不能在您的代码中假设TBar )。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM