C#如何实现带多泛型参数的并行查询方法并返回多类型结果集合
核心实现思路
C# 的 List<T> 确实只支持单个泛型参数,无法直接承载多类型结果,针对你的场景有两种成熟的实现方案:
方案1:固定泛型参数重载(推荐)
你提到最多同时查询3-4个表,这种方案实现成本最低且完全类型安全,利用C#的值元组承载多类型返回结果,只需要写2/3/4个参数的重载即可适配需求。
同步实现示例
// 2个查询的重载 public (List<T1> Result1, List<T2> Result2) Query<T1, T2>(params QueryModel[] queries) where T1 : BaseClass where T2 : BaseClass { if (queries.Length != 2) throw new ArgumentException("查询数量需与泛型参数数量一致"); var results = new object[2]; // 并行执行查询 Parallel.For(0, 2, i => { // 这里复用你原有单查询的获取数据逻辑 var rawData = GetRawDataFromQuery(queries[i]); var targetType = i == 0 ? typeof(T1) : typeof(T2); results[i] = JsonSerializer.Deserialize(rawData, typeof(List<>).MakeGenericType(targetType)); }); return ((List<T1>)results[0], (List<T2>)results[1]); } // 3个查询的重载 public (List<T1> Result1, List<T2> Result2, List<T3> Result3) Query<T1, T2, T3>(params QueryModel[] queries) where T1 : BaseClass where T2 : BaseClass where T3 : BaseClass { if (queries.Length != 3) throw new ArgumentException("查询数量需与泛型参数数量一致"); var results = new object[3]; Parallel.For(0, 3, i => { var rawData = GetRawDataFromQuery(queries[i]); var targetType = i switch { 0 => typeof(T1), 1 => typeof(T2), 2 => typeof(T3), _ => throw new IndexOutOfRangeException() }; results[i] = JsonSerializer.Deserialize(rawData, typeof(List<>).MakeGenericType(targetType)); }); return ((List<T1>)results[0], (List<T2>)results[1], (List<T3>)results[2]); } // 4个查询的重载按照上述逻辑扩展即可
IO密集型场景异步优化示例
如果你的查询是数据库/接口等IO密集型操作,更推荐用异步并行实现,性能更高:
public async Task<(List<T1> Result1, List<T2> Result2, List<T3> Result3)> QueryAsync<T1, T2, T3>(params QueryModel[] queries) where T1 : BaseClass where T2 : BaseClass where T3 : BaseClass { if (queries.Length != 3) throw new ArgumentException("查询数量需与泛型参数数量一致"); // 并行发起所有异步查询 var dataTasks = queries.Select(q => GetRawDataFromQueryAsync(q)).ToList(); var rawDataResults = await Task.WhenAll(dataTasks); // 按顺序反序列化对应类型 var res1 = JsonSerializer.Deserialize<List<T1>>(rawDataResults[0]); var res2 = JsonSerializer.Deserialize<List<T2>>(rawDataResults[1]); var res3 = JsonSerializer.Deserialize<List<T3>>(rawDataResults[2]); return (res1, res2, res3); }
调用方式
完全类型安全,编译期即可校验类型匹配:
// 调用3参数重载,直接拿到对应类型的结果 var (userList, orderList, logList) = Query<UserDto, OrderDto, LogDto>(userQuery, orderQuery, logQuery);
该方案优势是调用端不需要手动转型,代码简洁易维护,完全适配你的现有需求。
方案2:可变数量泛型查询
如果需要支持任意数量的并行查询,可以采用查询绑定返回类型的方案实现:
实现示例
public List<object> QueryMany(params (QueryModel Query, Type ReturnType)[] queryConfigs) { var results = new List<object>(queryConfigs.Length); Parallel.ForEach(queryConfigs, config => { var rawData = GetRawDataFromQuery(config.Query); var result = JsonSerializer.Deserialize(rawData, typeof(List<>).MakeGenericType(config.ReturnType)); lock(results) results.Add(result); }); return results; }
调用方式
var results = QueryMany( (userQuery, typeof(UserDto)), (orderQuery, typeof(OrderDto)), (logQuery, typeof(LogDto)), (otherQuery, typeof(OtherDto)) ); // 手动转型使用 var userList = (List<UserDto>)results[0]; var orderList = (List<OrderDto>)results[1];
该方案灵活性更高,支持任意数量的并行查询,但调用端需要手动做类型转换,丢失了编译期类型安全校验。
内容的提问来源于stack exchange,提问作者Maulik
相关产品推荐
相关产品推荐

