我正试图在我的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”
为什么转换是不可能的?
发布于 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();
}
发布于 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();
时编译器会抱怨的原因。
https://stackoverflow.com/questions/56571409
复制相似问题