在C#开发中,LINQ(Language Integrated Query,语言集成查询)是一项非常实用的特性,它允许开发者使用类似SQL的语法直接在C#代码中查询各种数据源,其中对List集合的查询和筛选是最常用的场景之一。通过LINQ,我们可以避免编写大量的循环遍历代码,让数据操作逻辑更加简洁清晰。

LINQ的基础使用方式
LINQ有两种常见的书写形式,一种是查询表达式语法,另一种是方法语法。两种方式最终实现的功能是一致的,开发者可以根据自己的习惯选择使用。
1. 查询表达式语法
查询表达式语法的结构和SQL语句比较相似,可读性较强,适合处理复杂的查询逻辑。下面是一个查询List中符合条件元素的基础示例,首先我们定义一个学生类:
// 定义学生类
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public string Grade { get; set; }
}
接下来创建一个Student类型的List集合,并使用查询表达式筛选出年龄大于18岁的学生:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// 初始化学生列表
List<Student> studentList = new List<Student>
{
new Student { Id = 1, Name = "张三", Age = 17, Grade = "高二" },
new Student { Id = 2, Name = "李四", Age = 19, Grade = "高三" },
new Student { Id = 3, Name = "王五", Age = 18, Grade = "高二" },
new Student { Id = 4, Name = "赵六", Age = 20, Grade = "高三" }
};
// 使用查询表达式筛选年龄大于18的学生
var adultStudents = from student in studentList
where student.Age > 18
select student;
// 输出结果
Console.WriteLine("年龄大于18的学生:");
foreach (var student in adultStudents)
{
Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},年级:{student.Grade}");
}
}
}
2. 方法语法
方法语法是通过调用LINQ扩展方法来实现查询,链式调用的形式让代码更加紧凑,适合简单的查询场景。同样是筛选年龄大于18岁的学生,方法语法的实现如下:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<Student> studentList = new List<Student>
{
new Student { Id = 1, Name = "张三", Age = 17, Grade = "高二" },
new Student { Id = 2, Name = "李四", Age = 19, Grade = "高三" },
new Student { Id = 3, Name = "王五", Age = 18, Grade = "高二" },
new Student { Id = 4, Name = "赵六", Age = 20, Grade = "高三" }
};
// 使用方法语法筛选年龄大于18的学生
var adultStudents = studentList.Where(student => student.Age > 18);
Console.WriteLine("年龄大于18的学生:");
foreach (var student in adultStudents)
{
Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},年级:{student.Grade}");
}
}
}
常见的List筛选场景示例
多条件筛选
实际开发中经常需要同时满足多个条件,比如筛选高三年级且年龄大于等于19岁的学生:
// 多条件筛选:高三年级且年龄大于等于19岁
var targetStudents = studentList
.Where(student => student.Grade == "高三" && student.Age >= 19)
.ToList();
Console.WriteLine("高三年级且年龄大于等于19的学生:");
foreach (var student in targetStudents)
{
Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},年级:{student.Grade}");
}
筛选后排序
可以在筛选完成后对结果进行排序,比如筛选年龄大于17岁的学生,再按照年龄升序排列:
// 筛选后排序:年龄大于17岁,按年龄升序
var sortedStudents = studentList
.Where(student => student.Age > 17)
.OrderBy(student => student.Age)
.ToList();
Console.WriteLine("年龄大于17岁的学生(按年龄升序):");
foreach (var student in sortedStudents)
{
Console.WriteLine($"姓名:{student.Name},年龄:{student.Age},年级:{student.Grade}");
}
筛选后投影到新类型
有时候我们不需要返回完整的Student对象,只需要部分字段,可以通过Select方法投影到新的匿名类型或者自定义类型:
// 筛选后投影:只获取姓名和年龄
var studentInfoList = studentList
.Where(student => student.Age > 18)
.Select(student => new { student.Name, student.Age })
.ToList();
Console.WriteLine("年龄大于18的学生姓名和年龄:");
foreach (var info in studentInfoList)
{
Console.WriteLine($"姓名:{info.Name},年龄:{info.Age}");
}
LINQ查询的注意事项
- LINQ查询默认是延迟执行的,只有在遍历结果或者调用
ToList、Count等方法时才会真正执行查询,因此如果需要多次使用查询结果,建议先调用ToList缓存结果。 - 使用
Where方法筛选时,如果原List中没有符合条件的元素,会返回一个空的集合,不会返回null,因此不需要额外做null判断。 - 复杂的条件筛选可以拆分多个
Where方法调用,也可以在一个lambda表达式中写多个条件,两种方式执行效率基本一致,可以根据可读性选择。