将派生类赋值给具有泛型的基类变量

本文关键字:泛型 基类 类变量 派生 赋值 | 更新日期: 2023-09-27 18:16:33

我有一组具有相对简单的层次结构的类和接口,但是有继承的东西,然后有一个接受基类的变量不能很好地工作。我认为问题是我的动态类型必须是where : class而不是where : IEntity,因为这些类型在我无法改变的函数中使用。

public interface IB<X, Y> 
    where X : class, IEntity 
    where Y : class, IEntity
{
    ...
}
public abstract class A
{
    ...
}
public abstract class B<X, Y> : A, IB<X, Y> 
    where X : class, IEntity 
    where Y : class, IEntity
{
    ...
}
public interface IEntity
{
    ...
}
public class Entity1 : IEntity
{
    ...
}
public class Entity2 : IEntity
{
    ...
}
public class C : B<Entity1, Entity2>, IB<Entity1, Entity2>
{
   ...
}

然后,尝试在函数中使用所有这些…

C c = new C();
IB<IEntity, IEntity> ib = c;

不能隐式或显式强制转换this。

我怎样才能使它工作?

将派生类赋值给具有泛型的基类变量

您的接口不是协变有效的。也就是说,

IB<IEntity, IEntity>IB<Entity1, Entity2>不是一回事。要解决这个问题,可以在接口定义

中的类型参数上使用out关键字。
public interface IB<out X, out Y> where X : class where Y : class
作为第二点,您需要将约束级联到类B
public abstract class B<X, Y> : A, IB<X, Y> where X : class where Y : class

有了这些修改,你将C赋值到ib是合法的。

C c = new C(); 
IB<IEntity, IEntity> ib = c;

(正如Davy8在评论中正确指出的,这个接口协方差特性需要c# 4+)

您需要更改class B的定义如下:

public abstract class B<X, Y> : A, IB<X, Y> where X : class where Y : class 
{
    ...
}

约束必须在整个继承链中指定。