4

我有以下代码。

class Header<T> where T: IItem { }
class HeaderA : Header<ItemA> { } 
class HeaderB : Header<ItemB> { } 

interface IItem { }
class ItemA : IItem { }
class ItemB : IItem { }

Header<IItem> h = new HeaderA();

最后一行无法编译。

Cannot implicitly convert type 'UserQuery.HeaderA' to 'UserQuery.Header<UserQuery.IItem>'

HeaderA 是 Header 的子类型,ItemA 是 IItem 的子类型。为什么它不起作用?

4

1 回答 1

16

简而言之,您正在尝试使用一个名为covariance的概念,该概念在.NET 泛型类中不受支持,并且默认情况下在接口中不受支持。

如果您想允许该类执行此操作,您可以在 C# 3 或更高版本中使用通用接口上的outcontextual 关键字指定它:

interface IHeader<out T> where T : IItem { }
class Header<T>: IHeader<T> where T:IItem { }
class HeaderA : Header<ItemA> { }
class HeaderB : Header<ItemB> { }

interface IItem { }
class ItemA : IItem { }
class ItemB : IItem { }

public void Foo()
{
    //now this works; notice the use of the interface instead of the base class.
    IHeader<IItem> h = new HeaderA();
}

通过使用带关键字的接口,您基本上是在告诉编译器,只要接口满足接口的泛型类型声明的约束(或者它是一个对象),就不必了解更多关于泛型类型的信息。因此,虽然您现在可以将更多派生泛型分配给接口类型的变量,但您只能将它们作为接口类型处理,而不能作为任何派生类型处理。

out关键字对于类定义是不可接受的;您不能强制使用 ofHeader<T>是协变的。

于 2012-09-14T20:22:38.227 回答