首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么继承的接口不能在泛型上下文中转换为它的基接口?

为什么继承的接口不能在泛型上下文中转换为它的基接口?
EN

Stack Overflow用户
提问于 2019-06-13 07:06:16
回答 2查看 350关注 0票数 1

我正试图在我的C#项目中实现一个接口继承系统,但是我无法让它工作。

这是一个简化的版本:

public interface BaseInterface {}

public abstract class AbstractClass<T> where T : BaseInterface {}

public interface ChildInterface : BaseInterface {}

public class ConcreteClass : AbstractClass<ChildInterface> {}

我想按如下方式使用它:

AbstractClass<BaseInterface> c = new ConcreteClass();

最后一行代码显示以下错误:

不能将类型“ConcreteClass”隐式转换为“AbstractClass”

为什么转换是不可能的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2019-06-13 07:42:33

您无法进行赋值,因为基类AbstractClass<T>是不变的。您希望能够进行这种赋值的是协变类型。定义协方差和逆方差仅限于接口,因此这意味着我们需要另一个接口。

public interface IAbstractClass<out T> where T : BaseInterface { }  
public abstract class AbstractClass<T> : IAbstractClass<T> where T : BaseInterface { }

out关键字将泛型类型参数标记为协变。然后,我们在AbstractClass<T>中实现该接口,并且我们的其他类型可以通过该接口正常工作。这些也是我们需要做的唯一修改,我们保持其他类型定义不变:

public interface BaseInterface { }
public interface ChildInterface : BaseInterface { }

public class ConcreteClass : AbstractClass<ChildInterface> { }

我们现在有了AbstractClass<T>实现的协变接口,您可以执行所需类型的赋值,但您必须以IAbstractClass接口为目标。

public void Main() {
    IAbstractClass<BaseInterface> c = new ConcreteClass();
}
票数 3
EN

Stack Overflow用户

发布于 2019-06-13 12:13:54

让我们来玩玩你的类型,并给它们起个不同的名字。

public interface IFruit { }

public abstract class BowlOf<Fruit> where Fruit : IFruit
{
    public void Add(Fruit fruit) { }
}

public class Apple : IFruit { }

public class BowlOfApples : BowlOf<Apple> { }

现在,这只是一个类型的重命名(但将public interface ChildInterface : BaseInterface {}更改为public class Apple : IFruit { }),然后我们创建以下问题。

假设我也有public class Banana : IFruit { },并且假设以下内容是合法的:

BowlOf<IFruit> c = new BowlOfApples();

那我可以给c.Add(new Banana())打电话了。什么!?!你不能在一碗苹果里加香蕉。

这就是为什么当你尝试做AbstractClass<BaseInterface> c = new ConcreteClass();时编译器会抱怨的原因。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56571409

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档