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

如何用LINQ连接不同对象列表生成指定新列表?有无非Concat+包装类方案?

核心LINQ实现(基于关联查询的高效方案)

这是个典型的跨集合关联查询场景,用LINQ的Join方法就能轻松搞定,它专门针对这种基于键匹配的场景做了优化,内部会用哈希表降低查询复杂度,性能比嵌套循环好很多。下面是几种不用自定义包装类的实现方式:

1. 匿名类型(当前上下文直接用)

如果只在当前方法里使用结果,匿名类型是最省事的选择——不用额外写类,语法也简洁:

var output = objAs.Join(
    objBs,
    a => a.ObjBId,  // ObjA的关联键
    b => b.Id,      // ObjB的关联键
    (a, b) => new { ObjAId = a.Id, ObjBTitle = b.Title }  // 映射需要的字段
).ToList();

唯一的限制是匿名类型不能跨方法传递,只能在当前代码块里用。

2. ValueTuple(跨方法友好,C#7.0+支持)

如果需要把结果传到其他方法,又不想写包装类,ValueTuple完美适配——它是值类型,还能给字段命名,可读性拉满:

var output = objAs.Join(
    objBs,
    a => a.ObjBId,
    b => b.Id,
    (a, b) => (ObjAId: a.Id, ObjBTitle: b.Title)
).ToList();

返回的List<(int ObjAId, string ObjBTitle)>可以直接给其他方法用,调用方一眼就能看懂字段含义。

3. Tuple(兼容旧版C#)

如果项目还在用C#7.0之前的版本,Tuple是传统替代方案,不过它的字段只能用Item1、Item2访问,可读性差一点:

var output = objAs.Join(
    objBs,
    a => a.ObjBId,
    b => b.Id,
    (a, b) => Tuple.Create(a.Id, b.Title)
).ToList();

取值的时候要用item.Item1(对应ObjA的Id)和item.Item2(对应ObjB的Title)。

除Concat和自定义包装类之外的替代方案

先说明下:Concat本来就不适合这个场景——它只是简单合并两个集合,根本做不到基于键的关联,所以你排除它是完全合理的。下面是两种不用包装类的替代实现:

1. Select + FirstOrDefault(适合小数据量)

如果你的数据集很小,性能要求不高,可以直接遍历ObjA,逐个匹配ObjB:

var output = objAs.Select(a => new {
    a.Id,
    Title = objBs.FirstOrDefault(b => b.Id == a.ObjBId)?.Title
}).ToList();

⚠️ 注意:这种方式是嵌套循环逻辑,时间复杂度O(n*m),数据量大的时候性能会很差,只推荐小数据集用。

2. 字典映射 + Select(性能接近Join)

先把ObjB转成以Id为键的字典,再用Select做匹配,查询效率是O(1),整体性能和Join差不多,逻辑也更直观:

var objBDict = objBs.ToDictionary(b => b.Id, b => b.Title);
var output = objAs.Select(a => new {
    a.Id,
    Title = objBDict.TryGetValue(a.ObjBId, out var title) ? title : null
}).ToList();

这种方式适合数据量较大的场景,而且手动控制映射逻辑,灵活性更高。

总结
  • 追求性能和标准写法,优先用Join配合匿名类型/ValueTuple;
  • 小数据量可以用Select+FirstOrDefault快速实现;
  • 想手动控制关联逻辑且兼顾性能,字典+Select是不错的选择;
  • 以上所有方案都不需要自定义包装类,完全满足你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 14:52:30