派生类型的通用基类

ca9*_*3d9 3 c# oop types covariance

我有以下代码.

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();
Run Code Online (Sandbox Code Playgroud)

最后一行无法编译.

Cannot implicitly convert type 'UserQuery.HeaderA' to 'UserQuery.Header<UserQuery.IItem>'
Run Code Online (Sandbox Code Playgroud)

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

Kei*_*thS 15

简而言之,您尝试使用称为协方差的概念,这在.NET泛型类中不受支持,并且在接口中默认不受支持.

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

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();
}
Run Code Online (Sandbox Code Playgroud)

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

out关键字不是类定义上可接受的; 你不能强迫使用Header<T>是协变的.