LINQ to Objects #
一、LINQ to Objects概述 #
1.1 什么是LINQ to Objects #
LINQ to Objects是对实现了IEnumerable
1.2 特点 #
- 内存中查询
- 延迟执行
- 链式调用
- 类型安全
二、延迟执行 #
2.1 什么是延迟执行 #
csharp
var numbers = new List<int> { 1, 2, 3 };
var query = numbers.Where(n => n > 1);
numbers.Add(4);
foreach (var n in query)
{
Console.WriteLine(n);
}
2.2 延迟执行的操作符 #
- Where
- Select
- OrderBy
- GroupBy
- Take
- Skip
2.3 重复执行 #
csharp
var numbers = new[] { 1, 2, 3 };
var query = numbers.Where(n => n > 1);
Console.WriteLine(query.Count());
Console.WriteLine(query.Sum());
Console.WriteLine(query.Average());
2.4 缓存结果 #
csharp
var numbers = new[] { 1, 2, 3 };
var query = numbers.Where(n => n > 1).ToList();
Console.WriteLine(query.Count);
Console.WriteLine(query.Count);
三、立即执行 #
3.1 什么是立即执行 #
csharp
var numbers = new[] { 1, 2, 3, 4, 5 };
List<int> list = numbers.Where(n => n > 2).ToList();
int[] array = numbers.Where(n => n > 2).ToArray();
int count = numbers.Count(n => n > 2);
int sum = numbers.Sum();
3.2 立即执行的操作符 #
- ToList
- ToArray
- ToDictionary
- ToLookup
- Count
- Sum
- Average
- First
- Last
- Any
- All
四、查询优化 #
4.1 避免多次枚举 #
csharp
var numbers = Enumerable.Range(1, 1000000);
var filtered = numbers.Where(n => n % 2 == 0).ToList();
var count = filtered.Count;
var sum = filtered.Sum;
var average = filtered.Average;
4.2 使用合适的集合 #
csharp
var list = new List<int> { 1, 2, 3, 4, 5 };
var set = new HashSet<int> { 1, 2, 3, 4, 5 };
bool contains = set.Contains(3);
4.3 提前过滤 #
csharp
var numbers = Enumerable.Range(1, 1000000);
var result = numbers
.Where(n => n % 2 == 0)
.Where(n => n > 500000)
.Take(100)
.ToList();
五、常见场景 #
5.1 分页查询 #
csharp
public static IEnumerable<T> GetPage<T>(IEnumerable<T> source, int page, int pageSize)
{
return source.Skip((page - 1) * pageSize).Take(pageSize);
}
var numbers = Enumerable.Range(1, 100);
var page1 = GetPage(numbers, 1, 10);
var page2 = GetPage(numbers, 2, 10);
5.2 去重 #
csharp
var numbers = new[] { 1, 2, 2, 3, 3, 3, 4, 4, 4, 4 };
var distinct = numbers.Distinct();
var people = new[] { new { Name = "张三", Age = 25 }, new { Name = "张三", Age = 30 } };
var distinctByName = people.DistinctBy(p => p.Name);
5.3 分组统计 #
csharp
var people = new[]
{
new { Name = "张三", Age = 25, City = "北京" },
new { Name = "李四", Age = 25, City = "上海" },
new { Name = "王五", Age = 30, City = "北京" }
};
var stats = people
.GroupBy(p => p.City)
.Select(g => new { City = g.Key, Count = g.Count(), AvgAge = g.Average(p => p.Age) });
5.4 树形结构 #
csharp
public class TreeNode
{
public int Id { get; set; }
public int? ParentId { get; set; }
public List<TreeNode> Children { get; set; } = new();
}
public static List<TreeNode> BuildTree(IEnumerable<TreeNode> nodes)
{
var nodeDict = nodes.ToDictionary(n => n.Id);
var roots = new List<TreeNode>();
foreach (var node in nodes)
{
if (node.ParentId == null)
{
roots.Add(node);
}
else if (nodeDict.TryGetValue(node.ParentId.Value, out var parent))
{
parent.Children.Add(node);
}
}
return roots;
}
六、性能考虑 #
6.1 选择合适的操作符 #
csharp
var numbers = Enumerable.Range(1, 1000000);
var first = numbers.First(n => n > 500000);
var any = numbers.Any(n => n > 500000);
6.2 避免不必要的操作 #
csharp
var numbers = Enumerable.Range(1, 100);
var result = numbers
.Where(n => n > 50)
.Select(n => n * 2)
.ToList();
var result = numbers
.Select(n => n * 2)
.Where(n => n > 100)
.ToList();
七、总结 #
LINQ to Objects要点:
| 要点 | 说明 |
|---|---|
| 延迟执行 | 查询定义时不执行 |
| 立即执行 | ToList/ToArray等 |
| 链式调用 | 流畅API |
| 性能优化 | 避免多次枚举 |
下一步,让我们学习.NET生态!
最后更新:2026-03-26