首页 > 解决方案 > 无法将派生类对象添加到其基类类型的列表中

问题描述

我有以下类结构:

//BaseClass
public abstract class BaseClass<T> where T : Model
{
    public abstract T Data { get; set; }
    public BaseClass(T data) { Data = data; }
}

public abstract class Model
{
    public int Id { get; set; }
}

//ClassA
public class BaseClassA : BaseClass<ModelA>
{
    public override ModelA Data { get; set; }
    public BaseClassA(ModelA data) : base(data) { }
}

public class ModelA : Model { }

//ClassB
public class BaseClassB : BaseClass<ModelB>
{
    public override ModelB Data { get; set; }
    public BaseClassB(ModelB data) : base(data) { }
}

public class ModelB : Model { }

我想按如下方式使用它们:

List<BaseClass<Model>> myBaseList = new List<BaseClass<Model>>();
myBaseList.Add(new BaseClassA(new ModelA()));
myBaseList.Add(new BaseClassB(new ModelB()));

foreach (var item in myBaseList)
{
    if (item.Data.Id > 0)
    {
        //do stuff
    }
}

但我得到编译器异常:

无法从 BaseClassA 转换为 BaseClass<Model>

但是,我的印象是 BaseClassA 的类型为 BaseClass<ModelA> 将满足类型为 BaseClass<Model> 的要求。

例如,这不会产生任何错误:

List<Model> myModelList = new List<Model>();
myModelList.Add(new ModelA());
myModelList.Add(new ModelB());

我似乎无法理解我在哪里出错了。

标签: c#inheritance

解决方案


一种可能的解决方案是引入协变接口:

public interface IBase<out T> where T : Model
{
    T Data { get; }
}

public abstract class BaseClass<T> : IBase<T> where T : Model

然后使用您的列表的界面:

var myBaseList = new List<IBase<Model>>();
myBaseList.Add(new BaseClassA(new ModelA()));
myBaseList.Add(new BaseClassB(new ModelB()));

因为IBase声明Data为 get-only,所以这确保了类型安全。

在这里您仍然可以访问Data

foreach (var item in myBaseList)
{
    if (item.Data.Id > 0)
    {
        //do stuff
    }
}

推荐阅读