LINQ 和 Lambda 表达式基础概念
LINQ(Language Integrated Query,语言集成查询)是 C# 中的查询语法,用于对数据集合进行查询和操作。
Lambda 表达式是一种匿名函数(不声明方法名,只写一个方法体,这个方法体就是lambda表达式),用于简化委托和事件的编写,常用于简化 LINQ 操作。
基本 Lambda 表达式用法
Lambda 表达式的基本语法是**(参数) => 表达式或语句块**。例如:
Func<int, int> square = x => x * x;
Console.WriteLine(square(5)); // 输出 25
可以表示为 委托的代码,或者表示为 表达式树的代码,它所表示的表达式树可以编译为委托。
Lambda 表达式的特定委托类型取决于其参数和返回值。
不返回值的 Lambda 表达式对应于 Action 委托,具体取决于其参数数量。
返回值的 Lambda 表达式对应于 Func 委托,具体取决于其参数数量。
Lambda 运算符 =>,该运算符读为"goes to"
若要创建 Lambda 表达式,需要在 lambda 运算符左侧指定输入参数(如果有),然后在另一侧输入表达式或语句块。 例如,单行 Lambda 表达式 x => x * x 指定名为 x 的参数并返回 x 的平方值。
只有当输入参数为1时,Lambda表达式左边的一对小括号才可以省略。
输入参数的数量大于或者等于2时,Lambda表达式左边的一对小括号中的多个参数之间使用逗号分隔。 例如:
csharp
Func<int, int, int> add = (a, b) => a + b;
Console.WriteLine(add(3, 7)); // 输出 10
public Action SuccessPrompt =() => MessageBox.Show("执行成功!", "提示", messageBoxButtons.OK, MessageBoxIcon.Information); //没有参数,括号不能省略
public Func<int, int, bool> Compare = (x, y) => x > y;//判断x是否大于y
lambda 类型推理的一般规则如下:
-
Lambda 包含的参数数量必须与委托类型包含的参数数量相同。
-
Lambda 中的每个输入参数必须都能够隐式转换为其对应的委托参数。
-
Lambda 的返回值(如果有)必须能够隐式转换为委托的返回类型。
LINQ to Objects 有一个输入参数,其类型是泛型委托 Func<TResult> 系列中的一种。
LINQ 查询基础
LINQ 提供了两种语法形式:查询表达式和方法语法。以下是一个简单的查询示例:
List<int> numbers = new List<int> { 1, 2, 3, 4, 5 };
// 查询语法
var evenNumbers = from num in numbers
where num % 2 == 0
select num;
// 方法语法
var evenNumbers = numbers.Where(num => num % 2 == 0);
foreach (var num in evenNumbers)
{
Console.WriteLine(num); // 输出 2, 4
}
常用 LINQ 方法 (含标准查询运算符的 Lambda)
Where 过滤
var filtered = numbers.Where(n => n > 3);
Select 投影
var squares = numbers.Select(n => n * n);
OrderBy 排序
var ordered = numbers.OrderBy(n => n);
var descending = numbers.OrderByDescending(n => n);
集合操作
Any 和 All
bool hasEven = numbers.Any(n => n % 2 == 0);
bool allPositive = numbers.All(n => n > 0);
First 和 FirstOrDefault
int firstEven = numbers.First(n => n % 2 == 0);
int firstOrDefault = numbers.FirstOrDefault(n => n > 10); // 返回 0 如果没找到
分组和连接
GroupBy
var groups = numbers.GroupBy(n => n % 2 == 0 ? "Even" : "Odd");
Join
List<string> names = new List<string> { "1", "2", "3" };
var joined = numbers.Join(names,
num => num.ToString(),
name => name,
(num, name) => $"{num}:{name}");
聚合函数
Sum, Average, Count
int total = numbers.Sum();
double avg = numbers.Average();
int count = numbers.Count();
Aggregate
string concatenated = numbers.Aggregate("", (result, n) => result + n.ToString());
延迟执行与立即执行
大多数 LINQ 方法采用延迟执行,只有在实际枚举结果时才执行查询。要强制立即执行,可以使用 ToList() 或 ToArray():
var immediate = numbers.Where(n => n > 3).ToList();
高级用法:表达式树
Lambda 表达式可以转换为表达式树,用于动态构建查询:
Expression<Func<int, bool>> expr = num => num > 5;
实际应用示例
从对象集合中查询:
class Person {
public string Name { get; set; }
public int Age { get; set; }
}
List<Person> people = new List<Person> {
new Person { Name = "Alice", Age = 25 },
new Person { Name = "Bob", Age = 30 }
};
var names = people.Where(p => p.Age > 25).Select(p => p.Name);
性能注意事项
对于大型数据集,考虑使用 AsParallel() 进行并行查询:
var parallelQuery = numbers.AsParallel().Where(n => n % 2 == 0);
调试技巧
在调试 LINQ 查询时,可以使用 System.Diagnostics.Debug.WriteLine 输出中间结果,或在查询中添加临时 Select 语句检查数据状态。