如何在C#中使用抽象约束实例化泛型类

时间:2014-02-10 09:28:11

标签: c# generics inheritance type-constraints

我有以下课程:

public abstract class ThingBase { }

public class ThingA : ThingBase { }

以下通用类:

public class ThingOwner<ThingType> where ThingType : ThingBase { }

我想创建一个ThingOwner实例,如下所示:

ThingOwner<ThingBase> thingOwner = new ThingOwner<ThingA>();

使用此代码,我收到以下错误:“无法将类型'ThingOwner(ThingA)'隐式转换为'ThingOwner(ThingBase)'”

我无法想象如何让它发挥作用。我知道有很多关于泛型类和继承的现有讨论,但我几乎尝试了所有内容,但我找不到适用于我的解决方案。

谢谢!

3 个答案:

答案 0 :(得分:3)

您应该使用C#4.0中引入的covariance for generic types。为此,您需要使用接口而不是类:

public interface IThingOwner<out ThingType> where ThingType : ThingBase { }

public class ThingOwner<ThingType> : IThingOwner<ThingType>
    where ThingType : ThingBase
{

}


IThingOwner<ThingBase> thingOwner = new ThingOwner<ThingA>();

答案 1 :(得分:1)

仅支持接口的协方差/逆变。如果你需要课程,那么只有这些课程可以工作:

ThingOwner<ThingBase> thingOwner = new ThingOwner<ThingBase>();
ThingOwner<ThingA> thingOwner = new ThingOwner<ThingA>();

答案 2 :(得分:1)

除上述答案外还有一些解释。虽然您的问题可以理解,但请考虑以下事项:

声明您有一个接受类型参数ClassA的派生类。在ThingOwner<ClassA>中,只允许添加一个或来自ClassA的类的实例。当您将其转换为ThingOwner<BaseClass>时,突然允许添加ClassB的实例,该实例也来自BaseClass。这可能会损害您的程序,实际上是错误的。这就是为什么他们首先发明了仿制药。