如何检测列表中是否存在与调用者同类型的对象
问题:检查列表中是否存在同类型基类对象并执行对应逻辑
我有一个存储同一基类BaseType对象的列表,这些对象可从多处构造,但仅存在于该列表中。添加新对象时,我希望检查列表中是否已有同类型的对象,尝试实现的代码如下,但存在语法错误无法运行:
public class ListHolder { List<BaseType> a = new List<BaseType>(); } public abstract class BaseType { public BaseType(ListHolder listIn) { if (listIn.a.OfType<typeof(this)>().Any()) { listIn.a.OfType<typeof(this)>().ToList()[0].Reapply(); } else { listIn.Add(this); Apply(); } } protected abstract void Reapply(); protected abstract void Apply(); }
问题出在OfType<typeof(this)>的用法上:泛型方法OfType<T>的类型参数必须是编译时常量,无法用运行时计算的typeof(this)来指定。即使先定义Type t = typeof(this)再调用OfType<t>也不生效。
补充说明:期望实现的调用效果如下(构造函数内部完成列表添加逻辑):
public class DerivedType : BaseType { protected override void Reapply() {} protected override void Apply() {} } ListHolder b = new ListHolder(); b.a.Add((BaseType)Activator.CreateInstance(DerivedType)); // 应调用Apply b.a.Add((BaseType)Activator.CreateInstance(DerivedType)); // 应调用Reapply
解决思路与实现代码
核心思路是避开泛型参数的编译时限制,直接通过运行时类型匹配来查找列表中的同类型对象,具体实现如下:
1. 修正ListHolder的封装
先完善ListHolder类,提供合理的列表访问和添加方法,避免直接暴露内部列表:
public class ListHolder { // 封装内部列表,对外只读访问 public IReadOnlyList<BaseType> Items => _items.AsReadOnly(); private readonly List<BaseType> _items = new List<BaseType>(); // 提供添加对象的方法 public void Add(BaseType item) { _items.Add(item); } }
2. 修改BaseType构造函数逻辑
用GetType()获取当前实例的运行时类型,直接在列表中筛选匹配类型的对象:
public abstract class BaseType { public BaseType(ListHolder listIn) { var currentInstanceType = GetType(); // 查找列表中第一个同类型的对象 var existingItem = listIn.Items.FirstOrDefault(item => item.GetType() == currentInstanceType); if (existingItem != null) { // 已有同类型对象,调用其Reapply方法 existingItem.Reapply(); } else { // 无同类型对象,添加到列表并调用Apply listIn.Add(this); Apply(); } } protected abstract void Reapply(); protected abstract void Apply(); }
3. 派生类实现
派生类只需实现抽象方法,并正确调用基类构造函数:
public class DerivedType : BaseType { public DerivedType(ListHolder listIn) : base(listIn) { } protected override void Reapply() { // 自定义重复创建时的逻辑,比如刷新状态 Console.WriteLine("调用Reapply:已存在同类型对象"); } protected override void Apply() { // 自定义首次添加时的逻辑,比如初始化状态 Console.WriteLine("调用Apply:首次添加同类型对象"); } }
4. 测试调用
按照需求的调用方式(包括用Activator.CreateInstance的场景):
var holder = new ListHolder(); // 首次创建DerivedType,调用Apply new DerivedType(holder); // 输出:调用Apply:首次添加同类型对象 // 再次创建DerivedType,调用已存在对象的Reapply new DerivedType(holder); // 输出:调用Reapply:已存在同类型对象 // 用Activator.CreateInstance的场景 Activator.CreateInstance(typeof(DerivedType), holder); // 输出:调用Reapply:已存在同类型对象
内容的提问来源于stack exchange,提问作者Sinnombre
相关产品推荐
相关产品推荐

