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

无法使用反射时,如何快速查找Service子类列表中的指定泛型实例?

问题背景

我有一个基类Service:

class Service {

}

同时存在多个继承自Service的子类:

class Service1 : Service { }
class Service2 : Service { }
class Service3 : Service { }
...

这些子类的实例都存储在同一个List<Service>集合中:

List<Service> services = new List<Service>() { new Service1(), new Service2(), new Service3() };

由于不能使用反射,我当前用以下方法查找指定类型的实例:

public T GetService<T>() where T : Service {
    foreach (var service in services) {
        if (service is T) return (T)service;
    }
    return null;
}

// 调用示例
var instance = GetService<Service1>();

现在的问题是:当集合中的元素数量足够多时,如何实现更快速的查找?

优化方案

1. 构建类型-实例映射字典

一次性遍历原始集合,将每个实例按其实际类型存入Dictionary<Type, Service>,后续查找直接利用字典的O(1)时间复杂度索引,这是最直接高效的优化方式。

单实例场景(同类型仅存一个实例)

// 类内维护映射字典
private Dictionary<Type, Service> _serviceMap;

// 在services集合初始化完成后执行映射构建
private void InitServiceMap() {
    _serviceMap = new Dictionary<Type, Service>();
    foreach (var service in services) {
        // 若存在同类型多个实例,后遍历的会覆盖先存入的,根据业务需求调整
        _serviceMap[service.GetType()] = service;
    }
}

// 优化后的查找方法
public T GetService<T>() where T : Service {
    if (_serviceMap.TryGetValue(typeof(T), out var target)) {
        return (T)target;
    }
    return null;
}

多实例场景(同类型存在多个实例)

如果允许同类型有多个实例,可将字典的值改为List<Service>来存储同类型的所有实例:

private Dictionary<Type, List<Service>> _serviceMap;

private void InitServiceMap() {
    _serviceMap = new Dictionary<Type, List<Service>>();
    foreach (var service in services) {
        var serviceType = service.GetType();
        if (!_serviceMap.ContainsKey(serviceType)) {
            _serviceMap[serviceType] = new List<Service>();
        }
        _serviceMap[serviceType].Add(service);
    }
}

// 获取同类型所有实例
public List<T> GetServices<T>() where T : Service {
    if (_serviceMap.TryGetValue(typeof(T), out var instances)) {
        return instances.Cast<T>().ToList();
    }
    return new List<T>();
}

// 获取同类型第一个实例
public T GetService<T>() where T : Service {
    return GetServices<T>().FirstOrDefault();
}

2. 使用ILookup分组存储

如果services集合不会动态修改,可使用.NET内置的ILookup<Type, Service>完成分组,它的查找效率和字典一致,且语法更简洁:

private ILookup<Type, Service> _serviceLookup;

private void InitServiceLookup() {
    _serviceLookup = services.ToLookup(s => s.GetType());
}

public T GetService<T>() where T : Service {
    return _serviceLookup[typeof(T)].Cast<T>().FirstOrDefault();
}

3. 动态集合的同步维护

如果services集合需要动态增删实例,必须同步更新映射字典或分组集合,保证查找结果准确:

// 添加服务时同步更新字典
public void AddService(Service service) {
    services.Add(service);
    var serviceType = service.GetType();
    if (_serviceMap.ContainsKey(serviceType)) {
        _serviceMap[serviceType].Add(service);
    } else {
        _serviceMap[serviceType] = new List<Service> { service };
    }
}

// 删除服务时同步更新字典
public void RemoveService(Service service) {
    services.Remove(service);
    var serviceType = service.GetType();
    if (_serviceMap.TryGetValue(serviceType, out var instances)) {
        instances.Remove(service);
        if (instances.Count == 0) {
            _serviceMap.Remove(serviceType);
        }
    }
}

内容的提问来源于stack exchange,提问作者srnldai

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 03:52:12