You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何检测列表中是否存在与调用者同类型的对象

问题:检查列表中是否存在同类型基类对象并执行对应逻辑

我有一个存储同一基类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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 01:30:17