C#中的LINQ Join方法用于根据两个集合中元素的匹配键,将两个集合的元素关联起来,生成一个新的结果序列,类似SQL中的表连接操作。它支持内连接、分组连接等多种连接模式,能够满足大部分多集合关联查询的需求。

Join方法的基本语法
Join方法属于LINQ的扩展方法,最常用的重载形式如下:
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector
);
各个参数的含义如下:
- outer:第一个要连接的目标集合,也就是外集合
- inner:第二个要连接的集合,也就是内集合
- outerKeySelector:从外集合元素中提取关联键的函数
- innerKeySelector:从内集合元素中提取关联键的函数
- resultSelector:定义如何将外集合和内集合的匹配元素组合成结果元素的函数
内连接实现示例
内连接会返回两个集合中关联键匹配的所有元素组合,是最常用的连接模式。下面以学生和班级两个集合为例,演示内连接的实现:
// 定义学生类
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int ClassId { get; set; }
}
// 定义班级类
public class ClassInfo
{
public int ClassId { get; set; }
public string ClassName { get; set; }
}
class Program
{
static void Main(string[] args)
{
// 初始化学生集合
List<Student> students = new List<Student>
{
new Student { Id = 1, Name = "张三", ClassId = 101 },
new Student { Id = 2, Name = "李四", ClassId = 102 },
new Student { Id = 3, Name = "王五", ClassId = 101 },
new Student { Id = 4, Name = "赵六", ClassId = 103 }
};
// 初始化班级集合
List<ClassInfo> classes = new List<ClassInfo>
{
new ClassInfo { ClassId = 101, ClassName = "一年级一班" },
new ClassInfo { ClassId = 102, ClassName = "一年级二班" }
};
// 使用Join方法实现内连接,查询学生对应的班级信息
var studentClassQuery = students.Join(
classes,
student => student.ClassId,
classInfo => classInfo.ClassId,
(student, classInfo) => new
{
StudentId = student.Id,
StudentName = student.Name,
ClassName = classInfo.ClassName
}
);
// 输出查询结果
foreach (var item in studentClassQuery)
{
Console.WriteLine($"学生ID:{item.StudentId},姓名:{item.StudentName},班级:{item.ClassName}");
}
}
}
上述代码的执行结果会输出张三、李四、王五三个学生的信息,因为赵六的班级ID是103,在班级集合中不存在匹配项,所以内连接不会返回该学生的数据。
分组连接实现示例
分组连接会将内集合中与外集合元素匹配的所有元素分组,每个外集合元素对应一个分组,即使内集合中没有匹配项,外集合元素也会出现在结果中,对应分组为空。实现分组连接可以使用GroupJoin方法,示例如下:
class Program
{
static void Main(string[] args)
{
// 学生和班级集合初始化代码同上
// 使用GroupJoin实现分组连接
var classStudentGroup = classes.GroupJoin(
students,
classInfo => classInfo.ClassId,
student => student.ClassId,
(classInfo, studentGroup) => new
{
ClassName = classInfo.ClassName,
Students = studentGroup.Select(s => s.Name).ToList()
}
);
// 输出分组结果
foreach (var item in classStudentGroup)
{
Console.WriteLine($"班级:{item.ClassName},学生列表:{string.Join("、", item.Students)}");
}
}
}
上述代码会输出两个班级的学生列表,一年级一班包含张三和王五,一年级二班包含李四,即使后续有班级在班级集合中但学生集合没有对应学生,也会输出该班级,学生列表为空。
Join方法使用注意事项
- 关联键的类型必须一致,否则会导致编译错误,比如外集合的关联键是int类型,内集合的关联键也必须是int类型
- Join方法默认使用延迟执行,只有在遍历结果序列时才会真正执行连接操作
- 如果需要自定义键的比较规则,可以使用Join方法带
IEqualityComparer<TKey>参数的重载,传入自定义的比较器 - 当处理大量数据时,建议提前对集合的关联键建立索引,提升Join操作的执行效率