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

如何合并实现List接口的泛型ApiResult<T>实例?

问题描述

我有一组DTO及容器DTO,例如BankDetails和继承自List<BankDetails>的容器DTOListOfBankDetails。我有一个泛型网络方法,它可能返回多个容器DTO的ApiResult<T>,需要将它们合并为一个ApiResult<T>(但T并非始终为列表类型)。ApiResult类的MergeResult成员用于合并另一个ApiResult<T>,此时T为DTO集合(如ListOfBankDetails)。

当前实现的MergeResult方法如下:

public class ApiResult<T>
{
    public T Response { get; set; }

    public void MergeResult(ApiResult<T> toMerge)
    {
        if (Response != null && toMerge.Response != null)
        {
            (Response as List<object>).AddRange(toMerge.Response as List<object>);
        }
    }
}

但将Response转为List<object>会返回null;我也尝试了以下实现,但Concat操作后转换为T类型失败:

public void MergeResult(ApiResult<T> toMerge)
{
    if (Response != null && toMerge.Response != null)
    {
        Response = (T)((Response as IEnumerable<object>).Concat(toMerge.Response as IEnumerable<object>));
    }
}

请问如何合并两个实现List接口的泛型类型?

解决方案

方法一:利用非泛型IList接口直接添加元素

所有List<T>及其子类都实现了非泛型的IList接口,借助这个接口可以直接遍历并添加元素,避开泛型转换的问题:

public class ApiResult<T>
{
    public T Response { get; set; }

    public void MergeResult(ApiResult<T> toMerge)
    {
        if (Response == null || toMerge.Response == null)
            return;

        // 将Response转换为非泛型IList
        var currentCollection = Response as System.Collections.IList;
        var mergeCollection = toMerge.Response as System.Collections.IList;

        if (currentCollection != null && mergeCollection != null)
        {
            foreach (var item in mergeCollection)
            {
                currentCollection.Add(item);
            }
        }
    }
}

这个方案代码简洁,性能优于反射,兼容所有继承自List<T>的容器DTO,同时对非集合类型的T能自动跳过合并逻辑。

方法二:反射调用AddRange方法(兼容更多集合类型)

如果容器DTO可能实现了ICollection<T>但不是List<T>的子类,可以用反射动态获取并调用AddRange方法:

public class ApiResult<T>
{
    public T Response { get; set; }

    public void MergeResult(ApiResult<T> toMerge)
    {
        if (Response == null || toMerge.Response == null)
            return;

        // 获取当前T实现的ICollection<TItem>接口
        var collectionInterface = typeof(T).GetInterface(typeof(ICollection<>).FullName);
        if (collectionInterface == null)
            return;

        // 获取集合的元素类型
        var itemType = collectionInterface.GetGenericArguments()[0];
        // 获取AddRange方法(List<T>及部分集合类型实现了该方法)
        var addRangeMethod = typeof(T).GetMethod("AddRange", new[] { typeof(IEnumerable<>).MakeGenericType(itemType) });

        if (addRangeMethod != null)
        {
            addRangeMethod.Invoke(Response, new[] { toMerge.Response });
        }
    }
}

这个方案兼容性更强,只要目标集合类型带有AddRange方法就能工作,但反射会带来轻微的性能开销。

原实现失败原因

  • 第一种实现中,List<BankDetails>无法直接转换为List<object>:泛型List<T>不支持协变,即使BankDetails是引用类型,也不能向上转换为List<object>,所以转换结果为null。
  • 第二种实现中,Concat返回的是IEnumerable<object>,它不是T(比如ListOfBankDetails)的实例,强制类型转换必然失败,因为IEnumerable无法直接转为具体的集合类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:37:41