当前位置: 首页 > article >正文

C# --- LINQ

C# --- LINQ

  • 什么是LINQ
  • Fluent Syntax 和 SQL-Like Query
  • LINQ Operations

什么是LINQ

  • LINQ的全称为Language Integrated Query, 为各种查询(包括对象查询,数据库查询,XML查询) 提供了统一模型.
  • LINQ源于SQL,但比SQL更加强大,更加灵活.
  • LINQ可以用类似于SQL的形式对C# Collection中的对象进行查询
  • LINQ可以在代码中对数据库进行查询,编程语言和数据库之间配合上的鸿沟,也就是不用再手动拼接SQL字符串去查询数据库.
  • 可读性强:LINQ增加了代码的可读性,因此其他开发人员可以很轻松地理解和维护

Fluent Syntax 和 SQL-Like Query

  • LINQ 在C#中分为两种主要语法形式

方法语法(Method Syntax / Fluent Syntax)

  • 使用 扩展方法(如 Where(), Select())链式调用,直接操作集合或数据源。
  • 特点:
    基于 Lambda 表达式,灵活且功能全面。
    支持所有 LINQ 操作(某些操作仅能通过方法语法实现,如 Distinct())。
    可读性取决于链式调用的复杂度。
var results = students
    .Where(s => s.Age > 18)
    .OrderBy(s => s.Name)
    .Select(s => new { s.Name, s.Score });

2. 查询表达式语法(Query Syntax / SQL-like Syntax)

  • 使用类似 SQL 的声明式语法,以 from、where、select 等关键字编写。
  • 特点:
    语法更接近自然语言,适合复杂查询(如多表连接、分组)。
    编译时会转换为方法语法(本质是语法糖)。
    部分操作无法直接表达(需结合方法语法,如 Distinct())。
var results = 
    from s in students
    where s.Age > 18
    orderby s.Name
    select new { s.Name, s.Score };

混合使用示例

// 结合查询表达式和方法语法
var query = 
    (from s in students
     where s.Age > 18
     select s)
    .Distinct()
    .ToList();

总结

  • 方法语法:灵活、全面,适合大多数场景。
  • 查询表达式:提升复杂查询的可读性,尤其适合多表操作。
  • 本质一致:两种语法最终殊途同归,按需选择即可!

LINQ Operations

Where(过滤)

var students = new List<Student> { /* 学生对象列表 */ };
// 找到年龄大于 20 的学生
var result = students.Where(s => s.Age > 20);

Select(投影)

// 提取所有学生的姓名
var names = students.Select(s => s.Name);

OrderBy / OrderByDescending(排序)

// 按年龄升序排序
var ordered = students.OrderBy(s => s.Age);
// 按成绩降序排序
var orderedByScore = students.OrderByDescending(s => s.Score);

GroupBy(分组)

// 按班级分组
var groups = students.GroupBy(s => s.Class);

// 遍历分组
foreach (var group in groups) {
    Console.WriteLine($"Class {group.Key}:");
    foreach (var student in group) {
        Console.WriteLine(student.Name);
    }
}

First / FirstOrDefault(获取首个元素)

// 获取第一个年龄大于 20 的学生(可能抛异常)
var first = students.First(s => s.Age > 20);
// 安全获取(无匹配返回 null)
var firstOrDefault = students.FirstOrDefault(s => s.Age > 100);

Single / SingleOrDefault(唯一元素)

// 确保唯一匹配(否则抛异常)
var single = students.Single(s => s.Id == 123);
// 安全获取唯一元素
var singleOrDefault = students.SingleOrDefault(s => s.Id == 456);

Any / All(存在性检查)

// 是否有学生年龄 > 20
bool hasAdult = students.Any(s => s.Age > 20);
// 是否所有学生成绩 >= 60
bool allPassed = students.All(s => s.Score >= 60);

Count / Sum / Average(聚合)

// 统计年龄 > 20 的学生数量
int count = students.Count(s => s.Age > 20);
// 计算所有学生的平均分
double avgScore = students.Average(s => s.Score);
// 总成绩
double totalScore = students.Sum(s => s.Score);

Take / Skip(分页)

// 取前 5 条数据
var page1 = students.Take(5);
// 跳过前 5 条,取接下来的 5 条(分页)
var page2 = students.Skip(5).Take(5);

Join(连接)

var courses = new List<Course> { /* 课程列表 */ };
// 学生与课程通过 CourseId 连接
var joined = students.Join(
    courses,
    s => s.CourseId,
    c => c.Id,
    (s, c) => new { s.Name, CourseName = c.Name }
);

Distinct(去重)

// 去重后的所有班级名称
var distinctClasses = students.Select(s => s.Class).Distinct();

SelectMany(扁平化嵌套集合)

var classes = new List<Class> { /* 班级列表(含学生集合) */ };
// 所有班级的所有学生
var allStudents = classes.SelectMany(c => c.Students);

Union / Intersect / Except(集合操作)

var list1 = new List<int> { 1, 2, 3 };
var list2 = new List<int> { 3, 4, 5 };

var union = list1.Union(list2);          // {1,2,3,4,5}
var intersect = list1.Intersect(list2);  // {3}
var except = list1.Except(list2);        // {1,2}

OfType / Cast(类型筛选)

var mixedList = new ArrayList { 1, "apple", 2, "banana" };
// 提取所有字符串
var strings = mixedList.OfType<string>();

Aggregate(自定义聚合)

//对集合元素执行累积操作
int[] numbers = { 1, 2, 3, 4 };
// 计算乘积:1*2*3*4
int product = numbers.Aggregate((acc, num) => acc * num);
// 指定初始值(例如累加字符串)
string concatenated = numbers.Aggregate("", (acc, num) => acc + num.ToString());

Max / Min(极值)

var maxAge = students.Max(s => s.Age);
var minScore = students.Min(s => s.Score);

Last / LastOrDefault(获取最后一个元素)

// 最后一个年龄大于 20 的学生
var last = students.Last(s => s.Age > 20);
var lastOrDefault = students.LastOrDefault(s => s.Age > 100);

Reverse(反转顺序)

var reversed = numbers.Reverse(); // {4,3,2,1}

Concat(连接两个集合)

var list1 = new List<int> { 1, 2 };
var list2 = new List<int> { 3, 4 };
var combined = list1.Concat(list2); // {1,2,3,4}

SequenceEqual(判断集合相等性)

var listA = new List<int> { 1, 2 };
var listB = new List<int> { 1, 2 };
bool isEqual = listA.SequenceEqual(listB); // true

DefaultIfEmpty(空集合默认值)

var emptyList = new List<int>();
// 若集合为空,返回包含默认值的单元素集合
var result = emptyList.DefaultIfEmpty(0); // {0}

Zip(合并两个集合)

var names = new[] { "Alice", "Bob" };
var ages = new[] { 25, 30 };
// 合并为元组:("Alice",25), ("Bob",30)
var zipped = names.Zip(ages, (name, age) => (name, age));

ToDictionary / ToLookup(转换为字典或分组字典)

// 将学生列表转为以Id为键的字典
var dict = students.ToDictionary(s => s.Id);
// 创建分组查找结构(类似 GroupBy,但立即执行)
var lookup = students.ToLookup(s => s.Class);

TakeWhile / SkipWhile(条件分页)

int[] nums = { 1, 2, 3, 4, 5, 1 };
// 取元素直到遇到 >=3 的值
var takeWhile = nums.TakeWhile(n => n < 3); // {1,2}
// 跳过元素直到遇到 >=3 的值
var skipWhile = nums.SkipWhile(n => n < 3); // {3,4,5,1}

ElementAt / ElementAtOrDefault(按索引访问)

var thirdStudent = students.ElementAt(2); // 索引从0开始
var safeElement = students.ElementAtOrDefault(100); // 越界返回 null

Range / Repeat(生成序列)

// 生成数字序列 10-14
var range = Enumerable.Range(10, 5); // {10,11,12,13,14}
// 生成重复值
var repeats = Enumerable.Repeat("Hello", 3); // {"Hello","Hello","Hello"}

Cast(强制类型转换)

var mixedList = new ArrayList { 1, 2, 3 };
// 转换为 IEnumerable<int>
var numbers = mixedList.Cast<int>();

DistinctBy / UnionBy(基于属性的去重/合并)

(需 .NET 6+ 或引入 System.Linq 的扩展包)
// 根据班级去重
var distinctByClass = students.DistinctBy(s => s.Class);
// 合并并去重(根据ID)
var unionBy = list1.UnionBy(list2, x => x.Id);

Chunk(分块)

//(需 .NET 6+)
int[] numbers = { 1, 2, 3, 4, 5 };
// 每块大小为2
var chunks = numbers.Chunk(2); // { {1,2}, {3,4}, {5} }

AsParallel(并行查询)

var bigData = Enumerable.Range(1, 1000000);
// 并行处理
var parallelResult = bigData.AsParallel()
                           .Where(n => n % 2 == 0)
                           .ToList();

OfType(过滤类型)

object[] objs = { 1, "apple", 2, "banana" };
// 提取所有整数
var ints = objs.OfType<int>(); // {1,2}

Prepend / Append(添加元素)

var nums = new[] { 2, 3 };
var newNums = nums.Prepend(1).Append(4); // {1,2,3,4}

LongCount(大集合计数)

// 返回 long 类型的计数(适用于超大集合)
long count = bigData.LongCount();

TakeLast / SkipLast(获取或跳过末尾元素)

int[] numbers = { 1, 2, 3, 4, 5 };
var lastTwo = numbers.TakeLast(2);       // {4,5}
var skipLastThree = numbers.SkipLast(3); // {1,2}

MaxBy / MinBy(按属性取极值对象)

//(需 .NET 6+)
// 取分数最高的学生
var topStudent = students.MaxBy(s => s.Score);
// 取年龄最小的学生
var youngest = students.MinBy(s => s.Age);

ToHashSet(快速去重集合)

//(需 .NET Framework 4.7.2+ 或 .NET Core 2.0+)
var uniqueNumbers = new[] { 1, 2, 2, 3 }.ToHashSet(); // {1,2,3}

ExceptBy / IntersectBy(基于键的集合操作)

var listA = new[] { new { Id = 1 }, new { Id = 2 } };
var listB = new[] { new { Id = 2 }, new { Id = 3 } };
// 按 Id 排除交集
var except = listA.ExceptBy(listB.Select(x => x.Id), x => x.Id); // {Id=1}

AsEnumerable / AsQueryable(切换执行上下文)

// 将 IQueryable 转为 IEnumerable(后续操作在内存执行)
var inMemoryQuery = dbContext.Students.AsEnumerable().Where(s => s.Age > 20);
// 将 IEnumerable 转为 IQueryable(用于动态构建数据库查询)
var queryable = students.AsQueryable().Where(s => s.Age > 20);

http://www.kler.cn/a/588546.html

相关文章:

  • 没有公网服务器的情况下,建立反弹 Shell
  • 网络编程、URI和URL的区别、TCP/IP协议、IP和端口、URLConnection
  • LLM(3): Transformer 架构
  • 数据结构-树(详解)
  • 力扣Hot100——35.搜索插入的位置(二分查找)
  • [C语言]数据在内存中的存储
  • ai数字人系统系统saas源码 一站式开发目录
  • 前端 git规范-不同软件(GitHub、Sourcetree、WebStorm)、命令行合并方式下增加 --no-ff的方法
  • 【Vue】上传PDF功能
  • 鸿蒙路由 HMrouter 配置及使用一
  • Android笔记:Android平台下SVG格式的解析与实践
  • PyTorch使用-张量数值计算
  • 每日Attention学习27——Patch-based Graph Reasoning
  • 【从零开始学习计算机科学】软件工程(六)软件质量
  • Docker基础知识介绍
  • 【Python+HTTP接口】POST请求不同请求头构造
  • 【ASMbits--常用算术运算指令】
  • 深入解析 FID:深度学习生成模型评价指标
  • pyQT学习笔记——Qt常用组件与绘图类的使用指南
  • 【商城实战(36)】UniApp性能飞升秘籍:从渲染到编译的深度优化