在C#的集合处理场景中,将大集合按照指定大小切割成多个小分块是常见需求,比如批量处理数据、分段传输内容等,LINQ内置的Chunk方法可以非常便捷地完成这类分块操作,不需要开发者手动编写循环逻辑。

Chunk方法的基本使用
Chunk是.NET 6及以上版本中LINQ新增的扩展方法,作用是将一个序列按照指定的块大小拆分成多个子序列,返回的结果是IEnumerable<IEnumerable<T>>类型,每个子序列就是对应大小的分块。
基础使用示例如下,将一个整数列表按照每块3个元素进行切割:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
// 原始待分块的整数集合
List<int> sourceList = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 调用Chunk方法,指定每块大小为3
IEnumerable<IEnumerable<int>> chunkResult = sourceList.Chunk(3);
int blockIndex = 1;
foreach (var block in chunkResult)
{
Console.Write($"第{blockIndex}块元素:");
foreach (var item in block)
{
Console.Write(item + " ");
}
Console.WriteLine();
blockIndex++;
}
}
}
上述代码执行后,输出结果如下:
第1块元素:1 2 3
第2块元素:4 5 6
第3块元素:7 8 9
第4块元素:10
可以看到最后一块元素不足指定大小时,会保留剩余的所有元素,不会丢弃。
Chunk方法的进阶使用场景
处理自定义对象集合
Chunk方法同样支持自定义类型的集合分块,比如我们有一个用户列表,需要按照每块5个用户进行批量处理:
using System;
using System.Collections.Generic;
using System.Linq;
// 定义用户实体类
public class User
{
public int Id { get; set; }
public string Name { get; set; }
}
class Program
{
static void Main()
{
List<User> userList = new List<User>
{
new User { Id = 1, Name = "张三" },
new User { Id = 2, Name = "李四" },
new User { Id = 3, Name = "王五" },
new User { Id = 4, Name = "赵六" },
new User { Id = 5, Name = "孙七" },
new User { Id = 6, Name = "周八" },
new User { Id = 7, Name = "吴九" }
};
// 按照每块3个用户分块
var userChunks = userList.Chunk(3);
foreach (var chunk in userChunks)
{
// 模拟批量处理每个分块的用户
Console.WriteLine("当前处理用户分块:");
foreach (var user in chunk)
{
Console.WriteLine($"用户ID:{user.Id},姓名:{user.Name}");
}
Console.WriteLine("------");
}
}
}
结合其他LINQ操作使用
Chunk方法可以和其他LINQ方法链式调用,比如先过滤集合再分块:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<int> numbers = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 先筛选出偶数,再按照每块2个分块
var evenChunks = numbers.Where(n => n % 2 == 0).Chunk(2);
foreach (var chunk in evenChunks)
{
Console.WriteLine("分块元素:" + string.Join(",", chunk));
}
}
}
上述代码会先过滤出2、4、6、8、10五个偶数,再按照每块2个切割,最终得到三个分块,最后一个分块只有元素10。
手动实现分块与Chunk方法的对比
在Chunk方法出现之前,开发者通常需要手动编写循环实现分块逻辑,手动实现示例如下:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<int> source = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int chunkSize = 3;
List<List<int>> manualChunks = new List<List<int>>();
List<int> currentChunk = new List<int>();
foreach (var item in source)
{
currentChunk.Add(item);
if (currentChunk.Count == chunkSize)
{
manualChunks.Add(currentChunk);
currentChunk = new List<int>();
}
}
// 添加最后不足chunkSize的剩余元素
if (currentChunk.Count > 0)
{
manualChunks.Add(currentChunk);
}
foreach (var chunk in manualChunks)
{
Console.WriteLine("手动分块元素:" + string.Join(",", chunk));
}
}
}
对比两种方式,Chunk方法的优势非常明显:
- 代码更简洁,不需要手动维护临时集合和计数逻辑
- 是LINQ官方实现,性能经过优化,处理大集合时效率更高
- 返回的是延迟执行的序列,不会一次性加载所有分块到内存,更节省内存
Chunk方法的注意事项
使用Chunk方法时需要注意以下几点:
- Chunk方法是.NET 6及以上版本才支持的,如果项目框架版本低于.NET 6,无法直接使用该方法,需要手动实现分块逻辑
- Chunk方法的块大小参数必须大于0,如果传入小于等于0的值,会抛出
ArgumentOutOfRangeException异常 - Chunk返回的子序列是只读的,不能对其进行修改操作,如果需要可修改的分块集合,可以手动转换为List类型
如果需要修改分块后的内容,可以这样处理:
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static void Main()
{
List<int> source = new List<int> { 1, 2, 3, 4, 5 };
// 将每个分块转换为List,方便后续修改
List<List<int>> mutableChunks = source.Chunk(2).Select(chunk => chunk.ToList()).ToList();
// 修改第一个分块的第一个元素
mutableChunks[0][0] = 100;
Console.WriteLine("修改后的第一个分块:" + string.Join(",", mutableChunks[0]));
}
}