在C#的LINQ查询中,Skip和Take是两个常用的分页相关方法,Skip用于跳过指定数量的元素,Take用于从序列中选取指定数量的元素,两者结合就能实现灵活的分页查询功能。

Skip和Take方法的基本说明
Skip方法的语法为Skip(int count),表示跳过序列中前count个元素,返回剩余的元素序列。如果count大于等于序列总长度,会返回空序列。
Take方法的语法为Take(int count),表示从序列开头选取count个元素,返回新的序列。如果count大于序列剩余长度,会返回所有剩余元素。
两者结合使用时,通常先计算需要跳过的数据量,再获取当前页的数据量,就能实现分页效果。
分页核心参数计算
实现分页需要明确几个核心参数:
- 当前页码:pageIndex,从1开始计数
- 每页数据量:pageSize,每页展示的数据条数
- 总数据量:totalCount,查询条件下的所有数据总数
- 总页数:totalPages,计算方式为(totalCount + pageSize - 1) / pageSize,避免整除时的计算误差
- 跳过数据量:skipCount,计算方式为(pageIndex - 1) * pageSize
完整项目实例
下面是一个控制台应用程序的完整示例,模拟用户数据列表的分页查询:
using System;
using System.Collections.Generic;
using System.Linq;
namespace LinqPaginationDemo
{
class Program
{
static void Main(string[] args)
{
// 模拟用户数据源,实际项目中可能来自数据库查询
List<User> userList = new List<User>
{
new User { Id = 1, Name = "张三", Age = 22 },
new User { Id = 2, Name = "李四", Age = 25 },
new User { Id = 3, Name = "王五", Age = 28 },
new User { Id = 4, Name = "赵六", Age = 30 },
new User { Id = 5, Name = "孙七", Age = 24 },
new User { Id = 6, Name = "周八", Age = 27 },
new User { Id = 7, Name = "吴九", Age = 29 },
new User { Id = 8, Name = "郑十", Age = 26 },
new User { Id = 9, Name = "冯十一", Age = 23 },
new User { Id = 10, Name = "陈十二", Age = 31 }
};
int pageSize = 3; // 每页展示3条数据
int totalCount = userList.Count; // 总数据量
int totalPages = (totalCount + pageSize - 1) / pageSize; // 计算总页数
Console.WriteLine("用户列表分页查询演示");
Console.WriteLine($"总数据量:{totalCount},每页数据量:{pageSize},总页数:{totalPages}");
Console.WriteLine("------------------------");
// 循环展示所有页的数据
for (int pageIndex = 1; pageIndex <= totalPages; pageIndex++)
{
// 计算需要跳过的数据量
int skipCount = (pageIndex - 1) * pageSize;
// 使用Skip和Take获取当前页数据
List<User> currentPageData = userList.Skip(skipCount).Take(pageSize).ToList();
Console.WriteLine($"第{pageIndex}页数据:");
foreach (var user in currentPageData)
{
Console.WriteLine($"Id:{user.Id},姓名:{user.Name},年龄:{user.Age}");
}
Console.WriteLine("------------------------");
}
// 模拟用户输入指定页码查询
Console.WriteLine("请输入要查询的页码:");
string input = Console.ReadLine();
if (int.TryParse(input, out int targetPage) && targetPage >= 1 && targetPage <= totalPages)
{
int skipCount = (targetPage - 1) * pageSize;
List<User> targetData = userList.Skip(skipCount).Take(pageSize).ToList();
Console.WriteLine($"第{targetPage}页数据:");
foreach (var user in targetData)
{
Console.WriteLine($"Id:{user.Id},姓名:{user.Name},年龄:{user.Age}");
}
}
else
{
Console.WriteLine("输入的页码无效");
}
}
}
// 用户实体类
class User
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
}
注意事项
在实际项目使用中需要注意以下几点:
- 如果数据源是数据库查询(如Entity Framework),Skip和Take会转换为对应的SQL分页语句,不会先把所有数据加载到内存再分页,性能较好
- 当pageIndex为1时,skipCount为0,Skip(0)不会影响查询结果,不需要额外做判断
- 如果查询条件会变化,需要先获取符合条件的总数据量,再计算分页参数,避免分页结果不准确
- Take的参数如果超过剩余数据量,只会返回剩余的所有数据,不需要额外处理边界情况
总结
通过LINQ的Skip和Take方法实现分页逻辑非常简单,核心就是计算好跳过的元素数量,再获取对应页的元素数量。这种方法不仅代码简洁,而且在配合ORM框架使用时能自动生成高效的分页SQL,适合大多数C#项目的分页需求。开发者可以根据实际业务场景调整分页参数和查询条件,快速实现对应的分页功能。