c# - 无法将派生类对象添加到其基类类型的列表中
问题描述
我有以下类结构:
//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());
我似乎无法理解我在哪里出错了。
解决方案
一种可能的解决方案是引入协变接口:
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
}
}
推荐阅读
- ios - 如何在单元测试期间以编程方式编辑 iPhone 可访问性设置?
- python - 在 Visual Studio Code 中本地禁用 Python 语言服务器的警告
- javascript - 在 cypress.io 中,如果没有元素,我如何计算元素数量而不通过测试?
- angular - 带有 CORS 请求的 NgFor 异常
- apache-camel - 属性值不可访问
- typescript - Vue + Typescript + webpack:将 html 导入组件
- c# - 我正在尝试使用此代码 sHdrMetadataFormatCurrentlySupported(HdrMetadataFormat.HDR10);
- azure - Azure 空间锚(unity3d) - 我将空间锚保存到云中,但 2 或 3 小时后无法找到它
- angular - 如何从Angular中的Web api为表中的项目创建视图
- c# - JQuery Ajax 函数未在 DNN 中调用后端方法