C# LINQ 从入门到精通——用 SQL 一样的语法操作集合,Where、Select、GroupBy 带你告别 foreach 地狱
目录为什么需要 LINQLINQ 的两种写法查询语法与方法语法最常用的 10 个标准查询运算符延迟执行 vs 立即执行重要概念LINQ to Objects 实战学生成绩分析LINQ to SQL 与 Entity Framework 初探综合实战员工薪资报表系统练习题答案及解析性能提示与避坑指南下一步学习建议1. 为什么需要 LINQ回想一下没有 LINQ 之前我们要从一个集合中筛选数据通常要写繁琐的foreach循环 if判断csharpListint numbers new Listint { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; Listint evenNumbers new Listint(); foreach (var n in numbers) { if (n % 2 0) evenNumbers.Add(n); }这还只是最简单的筛选如果需要排序、分组、连接多个集合代码会变得又长又难维护。LINQLanguage Integrated Query语言集成查询就是为了解决这个问题而生的。它允许你用类似 SQL 的语法直接写在 C# 代码中对数组、集合、数据库、XML 等数据源进行统一的查询操作。核心优势可读性强查询意图一目了然类型安全编译时检查避免运行时错误统一 API无论数据源是什么查询语法都一样2. LINQ 的两种写法LINQ 提供了两种等价的写法你可以根据自己的喜好选择。2.1 查询语法Query Syntax看起来就像 SQL 语句使用from、where、select等关键字csharpint[] numbers { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // 查询语法筛选出偶数并按降序排列 var result from n in numbers where n % 2 0 orderby n descending select n; foreach (var item in result) Console.Write(item ); // 输出8 6 4 22.2 方法语法Method Syntax / Fluent Syntax使用扩展方法如Where、Select配合 Lambda 表达式csharpvar result numbers.Where(n n % 2 0) .OrderByDescending(n n); // 输出同上2.3 哪种写法更好查询语法更接近 SQL容易上手但功能有限不支持所有操作符如TakeWhile。方法语法更强大、更灵活几乎所有 LINQ 操作都能用。推荐混用复杂查询用查询语法特殊操作用方法语法。大多数 C# 开发者偏好方法语法。3. 最常用的 10 个标准查询运算符运算符作用示例方法语法Where条件筛选list.Where(x x 10)Select投影转换list.Select(x x * 2)SelectMany展平嵌套集合list.SelectMany(x x.Items)OrderBy/OrderByDescending升序/降序排序list.OrderBy(x x.Age)ThenBy/ThenByDescending次要排序list.OrderBy(x x.Age).ThenBy(x x.Name)GroupBy分组list.GroupBy(x x.Category)Join内连接list1.Join(list2, ...)GroupJoin分组连接左外连接list1.GroupJoin(list2, ...)Any/All是否存在/是否全部满足list.Any(x x 5)First/FirstOrDefault取第一个元素list.First(x x 5)Single/SingleOrDefault取唯一元素list.Single(x x 5)Skip/Take分页list.Skip(10).Take(20)Aggregate累计求和、拼接等list.Aggregate((a,b) a b)每个运算符都返回一个新的集合或单个值不会修改原始集合。4. 延迟执行 vs 立即执行重要概念这是新手最容易踩的坑4.1 延迟执行Deferred Execution像Where、Select、OrderBy这些返回IEnumerableT的操作符它们不会立即执行而是在你开始遍历结果时才真正去查询数据源。csharpvar numbers new Listint { 1, 2, 3 }; var query numbers.Where(n n 1); // 此时还没执行查询 numbers.Add(4); // 修改了数据源 foreach (var n in query) // 这里才执行查询会包含 4 { Console.WriteLine(n); // 输出 2, 3, 4 }好处每次遍历都获取最新数据且可以组合多个操作只遍历一次集合。4.2 立即执行Immediate Execution像ToList()、ToArray()、Count()、First()等操作会立即执行查询并返回结果集合或单个值。csharpvar numbers new Listint { 1, 2, 3 }; var listResult numbers.Where(n n 1).ToList(); // 立即执行 numbers.Add(4); foreach (var n in listResult) // 不会包含 4因为已经固化 { Console.WriteLine(n); // 输出 2, 3 }记住延迟执行的查询结果是一个“查询对象”每次遍历都会重新执行。立即执行的结果是快照不受后续数据源变化影响。5. LINQ to Objects 实战学生成绩分析我们用一个学生列表来演示各种 LINQ 操作。5.1 准备数据csharppublic class Student { public int Id { get; set; } public string Name { get; set; } public string Class { get; set; } // 班级 public int Score { get; set; } } ListStudent students new ListStudent { new Student { Id 1, Name 张三, Class A班, Score 85 }, new Student { Id 2, Name 李四, Class B班, Score 92 }, new Student { Id 3, Name 王五, Class A班, Score 78 }, new Student { Id 4, Name 赵六, Class B班, Score 88 }, new Student { Id 5, Name 孙七, Class A班, Score 95 }, new Student { Id 6, Name 周八, Class C班, Score 60 }, };5.2 常见查询示例csharp// 1. 成绩大于 80 的学生按分数降序 var highScorers students.Where(s s.Score 80) .OrderByDescending(s s.Score); foreach (var s in highScorers) Console.WriteLine(${s.Name} - {s.Score}); // 2. 只显示姓名和班级投影 var nameClass students.Select(s new { s.Name, s.Class }); foreach (var item in nameClass) Console.WriteLine(${item.Name} 在 {item.Class}); // 3. 按班级分组计算每个班的平均分 var groupByClass students.GroupBy(s s.Class) .Select(g new { Class g.Key, AvgScore g.Average(s s.Score), Count g.Count() }); foreach (var g in groupByClass) Console.WriteLine($班级 {g.Class}平均分 {g.AvgScore:F2}人数 {g.Count}); // 4. 最高分的学生使用 OrderByDescending First var topStudent students.OrderByDescending(s s.Score).First(); Console.WriteLine($最高分{topStudent.Name} - {topStudent.Score}); // 5. 是否存在不及格学生Any bool hasFailed students.Any(s s.Score 60); Console.WriteLine($存在不及格{hasFailed}); // 6. 所有学生是否都及格All bool allPassed students.All(s s.Score 60); Console.WriteLine($全部及格{allPassed}); // 7. 取前 3 名分页 var top3 students.OrderByDescending(s s.Score).Take(3); foreach (var s in top3) Console.WriteLine($前三名{s.Name} - {s.Score}); // 8. 跳过前 3 名取剩下的分页 var rest students.OrderByDescending(s s.Score).Skip(3); foreach (var s in rest) Console.WriteLine($其余{s.Name} - {s.Score});6. LINQ to SQL 与 Entity Framework 初探LINQ 不仅能查内存中的集合还能查数据库这是通过LINQ to SQL或Entity Framework Core实现的。当你使用 EF Core 时可以这样查询数据库csharpusing (var db new SchoolContext()) { // 查询成绩大于 80 的学生实际会生成 SQL 语句 var highScorers db.Students .Where(s s.Score 80) .OrderByDescending(s s.Score) .ToList(); }EF Core 会把你的 LINQ 表达式翻译成 SQL发送给数据库执行并返回对象。这就是LINQ to Entities。核心要点对于IQueryableTEF Core 查询LINQ 操作是延迟执行的直到ToList()等立即执行方法才会生成 SQL。你写的 LINQ 语句不会加载所有数据到内存而是生成高效的 SQL。7. 综合实战员工薪资报表系统我们将构建一个控制台程序使用 LINQ 对员工数据进行复杂的统计分析。7.1 数据模型csharppublic class Employee { public int Id { get; set; } public string Name { get; set; } public string Department { get; set; } public double Salary { get; set; } public DateTime HireDate { get; set; } }7.2 生成测试数据csharpListEmployee employees new ListEmployee { new Employee { Id 1, Name Alice, Department HR, Salary 5000, HireDate new DateTime(2020, 1, 15) }, new Employee { Id 2, Name Bob, Department IT, Salary 8000, HireDate new DateTime(2019, 5, 20) }, new Employee { Id 3, Name Charlie, Department IT, Salary 9500, HireDate new DateTime(2018, 3, 10) }, new Employee { Id 4, Name David, Department Sales, Salary 6000, HireDate new DateTime(2021, 7, 1) }, new Employee { Id 5, Name Eva, Department HR, Salary 5200, HireDate new DateTime(2020, 11, 12) }, new Employee { Id 6, Name Frank, Department IT, Salary 7000, HireDate new DateTime(2022, 2, 28) }, new Employee { Id 7, Name Grace, Department Sales, Salary 7500, HireDate new DateTime(2019, 9, 5) }, };7.3 完整报表功能csharpstatic void Main() { // 1. 各部门平均薪资降序 var deptAvg employees.GroupBy(e e.Department) .Select(g new { Dept g.Key, AvgSalary g.Average(e e.Salary) }) .OrderByDescending(x x.AvgSalary); Console.WriteLine( 各部门平均薪资 ); foreach (var item in deptAvg) Console.WriteLine(${item.Dept}: {item.AvgSalary:C}); // 2. 薪资最高的前 3 名员工 var top3 employees.OrderByDescending(e e.Salary) .Take(3) .Select(e new { e.Name, e.Salary, e.Department }); Console.WriteLine(\n 薪资 Top 3 ); foreach (var e in top3) Console.WriteLine(${e.Name} ({e.Department}) - {e.Salary:C}); // 3. 各部门入职人数按年份分组 var hireByDeptYear employees.GroupBy(e e.Department) .Select(g new { Dept g.Key, Data g.GroupBy(e e.HireDate.Year) .Select(y new { Year y.Key, Count y.Count() }) }); Console.WriteLine(\n 各部门年度入职人数 ); foreach (var dept in hireByDeptYear) { Console.WriteLine($【{dept.Dept}】); foreach (var yearData in dept.Data.OrderBy(y y.Year)) Console.WriteLine($ {yearData.Year}年: {yearData.Count}人); } // 4. 统计各部门薪资总额、最高、最低 var stats employees.GroupBy(e e.Department) .Select(g new { Dept g.Key, Total g.Sum(e e.Salary), Max g.Max(e e.Salary), Min g.Min(e e.Salary), Count g.Count() }); Console.WriteLine(\n 各部门薪资统计 ); foreach (var s in stats) Console.WriteLine(${s.Dept}: 总额 {s.Total:C}, 最高 {s.Max:C}, 最低 {s.Min:C}, 人数 {s.Count}); // 5. 找出公司内薪资高于部门平均薪资的员工关联子查询 var aboveDeptAvg employees.Select(e new { Employee e, DeptAvg employees.Where(emp emp.Department e.Department) .Average(emp emp.Salary) }) .Where(x x.Employee.Salary x.DeptAvg) .Select(x new { x.Employee.Name, x.Employee.Salary, DeptAvg x.DeptAvg }); Console.WriteLine(\n 高于部门平均薪资的员工 ); foreach (var item in aboveDeptAvg) Console.WriteLine(${item.Name} (薪资 {item.Salary:C}) 高于部门平均 {item.DeptAvg:C}); }7.4 运行效果部分输出text 各部门平均薪资 IT: $8,166.67 Sales: $6,750.00 HR: $5,100.00 薪资 Top 3 Charlie (IT) - $9,500.00 Bob (IT) - $8,000.00 Grace (Sales) - $7,500.00 ...8. 练习题练习 1基本筛选与投影给定一个整数列表Listint numbers new Listint { 5, 12, 8, 3, 20, 15, 7, 9 };用 LINQ 筛选出大于 10 的数字并按降序输出。将每个数字乘以 2然后输出。取出前 3 个偶数。练习 2分组与聚合订单系统定义一个Order类OrderId,CustomerId,Product,Quantity,Price。创建包含 6~8 个订单的列表。按CustomerId分组计算每个客户的订单总金额。按Product分组计算每种产品的总销量和总销售额。找出消费总额最高的客户 ID。练习 3复杂查询——员工与部门关联定义Department类DeptId,DeptName和Employee类EmpId,Name,DeptId,Salary。创建部门和员工的对应关系多个员工属于一个部门。使用Join查询每个员工的姓名、薪资和部门名称。按部门分组计算每个部门的平均薪资并输出部门名称和平均薪资。选做查询平均薪资高于公司平均薪资的部门。9. 练习题答案及解析练习1 答案csharp// 1. 大于10降序 var result1 numbers.Where(n n 10).OrderByDescending(n n); // 2. 每个乘2 var result2 numbers.Select(n n * 2); // 3. 前3个偶数 var result3 numbers.Where(n n % 2 0).Take(3);练习2 答案核心代码csharp// 按客户分组计算总金额 var customerTotal orders.GroupBy(o o.CustomerId) .Select(g new { CustomerId g.Key, Total g.Sum(o o.Quantity * o.Price) }); // 按产品分组 var productStats orders.GroupBy(o o.Product) .Select(g new { Product g.Key, TotalQuantity g.Sum(o o.Quantity), TotalSales g.Sum(o o.Quantity * o.Price) }); // 最高消费客户 var topCustomer customerTotal.OrderByDescending(x x.Total).First().CustomerId;练习3 答案Join 示例csharp// 1. Join 查询 var empWithDept employees.Join(departments, e e.DeptId, d d.DeptId, (e, d) new { e.Name, e.Salary, DeptName d.DeptName }); // 2. 按部门平均薪资 var deptAvg employees.GroupBy(e e.DeptId) .Join(departments, g g.Key, d d.DeptId, (g, d) new { DeptName d.DeptName, AvgSalary g.Average(e e.Salary) }); // 3. 高于公司平均的部门选做 double companyAvg employees.Average(e e.Salary); var aboveAvgDepts deptAvg.Where(x x.AvgSalary companyAvg);10. 性能提示与避坑指南⚠️ 陷阱1多次遍历同一个延迟查询csharpvar query numbers.Where(n n 5); int count query.Count(); // 第一次遍历 foreach (var n in query) { } // 第二次遍历如果数据源是数据库查询这会导致两次 SQL 执行。解决如果反复使用先ToList()缓存。⚠️ 陷阱2在 LINQ 中修改数据源在foreach遍历查询结果时修改原始集合会引发异常。应先ToList()再遍历。⚠️ 陷阱3滥用Count()判断是否为空csharpif (list.Count() 0) { } // ❌ 会遍历整个集合 if (list.Any()) { } // ✅ 只要发现一个元素就返回 true性能更好⚠️ 陷阱4在Where中调用耗时方法Where中的委托会在每次遍历时执行如果里面有耗时操作如网络请求性能会很差。解决先在内存中准备好数据或使用Select预处理。✅ 最佳实践优先使用Any()而非Count() 0。链式调用时把Where等筛选操作放在前面减少后续处理的数据量。对数据库查询避免在Where中使用不能翻译为 SQL 的本地方法如DateTime.Now的复杂计算。使用Select投影时只选择需要的字段减少数据传输量。11. 下一步学习建议表达式树Expression Trees了解 LINQ to SQL 背后的编译原理。PLINQ并行 LINQ利用多核处理器加速查询。动态 LINQ在运行时构建查询字符串可用于动态报表。深入 EF Core掌握导航属性、Include、过滤等高级查询。实战项目用 LINQ 重构之前的学生管理系统、游戏角色系统把循环全部替换成 LINQ 语句。最后的话LINQ 是 C# 开发者最爱的特性之一它让数据查询变得像呼吸一样自然。你可能一开始觉得查询语法和方法语法有点绕但只要坚持写几个实际场景就会爱上它。今天的员工报表系统演示了 LINQ 在真实业务中的威力——分组、聚合、排序、关联查询一气呵成代码清晰且易于维护。记住两条黄金法则延迟执行是双刃剑——善用它但也别忘了ToList()来固定结果。能 LINQ 的就别手写循环——除非有极端的性能要求否则 LINQ 的可读性和生产力远超手写。把上面的练习做一遍再试着用 LINQ 重写你以前写过的最复杂的查询逻辑你会感受到质的飞跃。下一篇我们将进入异常处理与调试的世界让你的程序在出错时也能优雅应对。我们下一篇见下一篇预告C# 异常处理与调试技巧——try-catch-finally全方位解读教你写健壮的程序并掌握 Visual Studio 调试利器。敬请期待全文完

相关新闻

Windows系统文件dnsext.dll丢失找不到问题解决

Windows系统文件dnsext.dll丢失找不到问题解决

在使用电脑系统时经常会出现丢失找不到某些文件的情况,由于很多常用软件都是采用 Microsoft Visual Studio 编写的,所以这类软件的运行需要依赖微软Visual C运行库,比如像 QQ、迅雷、Adobe 软件等等,如果没有安装VC运行库或者安装…

2026/8/1 0:05:18 阅读更多 →
AI 乱改代码?试试这套 SDD 规范驱动工作流

AI 乱改代码?试试这套 SDD 规范驱动工作流

在 AI Coding 快速普及的这两年,越来越多的团队开始使用 Codex、Cursor、Claude Code 等工具辅助开发。围绕这些工具,也出现了大量关于 Prompt、Skills、MCP 的使用教程。但很多内容都停留在“单点提效”层面:教你怎么写 Prompt、怎么装工具、…

2026/7/31 18:15:52 阅读更多 →
基于LangGraph搭建医疗智能分诊RAG Agent

基于LangGraph搭建医疗智能分诊RAG Agent

前言很多开发者做RAG智能体只会用LangChain线性Chain实现,一旦业务出现分支判断、循环重试、多工具并行、会话断点续跑、多用户长期记忆,代码会大量嵌套、逻辑割裂、难以维护,完全不适合线上生产。LangGraph 作为 LangChain 官方推出的状态图…

2026/7/30 17:18:08 阅读更多 →

最新新闻

Cline v4.1.2 发布:Legacy/Next 双变体标识优化,迁移实录与兼容性分析

Cline v4.1.2 发布:Legacy/Next 双变体标识优化,迁移实录与兼容性分析

Cline v4.1.2 发布:Legacy/Next 双变体标识优化,迁移实录与兼容性分析上周收到团队反馈,升级Cline插件后Settings页面出现了"Legacy"和"Next"两个标识,开发者不清楚当前激活的是哪个变体,导致配置…

2026/8/2 22:59:04 阅读更多 →
开源大模型跨越临界点:从技术追赶到工程落地的实战指南

开源大模型跨越临界点:从技术追赶到工程落地的实战指南

1. 开源模型已经跨过了一个临界点最近和几个做AI应用的朋友聊天,大家不约而同地提到一个感觉:现在搞点AI功能,好像没那么“虚”了。以前想用个大模型能力,要么得花大价钱去调用商业API,要么就得自己吭哧吭哧搞个几百万…

2026/8/2 22:59:04 阅读更多 →
LangSmith可复用评估器与模板:构建AI应用的质量保障体系

LangSmith可复用评估器与模板:构建AI应用的质量保障体系

1. 项目概述:LangSmith中的可复用评估器与评估器模板如果你正在用LangChain或者LangGraph构建AI应用,那么“评估”这个环节大概率是你最头疼的部分之一。模型输出飘忽不定,提示词(Prompt)微调效果难以量化,…

2026/8/2 22:59:04 阅读更多 →
LangChain 2026:模块化工具包与RAG系统实战指南

LangChain 2026:模块化工具包与RAG系统实战指南

1. 从一份“迟到”的通讯说起:为什么我们还在讨论LangChain?如果你在2026年的今天,偶然翻到一份标题为“March 2026: LangChain Newsletter”的文档,第一反应会是什么?是“LangChain居然还在更新?”&#x…

2026/8/2 22:59:04 阅读更多 →
LangChain生态2026技术风向:从工具调用优化到LangGraph实战架构

LangChain生态2026技术风向:从工具调用优化到LangGraph实战架构

1. 项目概述:一份来自未来的技术风向标 如果你正在关注大语言模型应用开发,那么“LangChain Newsletter”这个名字对你来说一定不陌生。它不是一份普通的邮件列表,而是这个领域里许多开发者和架构师每月必读的“技术雷达”。想象一下&#x…

2026/8/2 22:59:04 阅读更多 →
使用wtrace诊断系统问题:实战案例分析与解决方案

使用wtrace诊断系统问题:实战案例分析与解决方案

使用wtrace诊断系统问题:实战案例分析与解决方案 【免费下载链接】wtrace Command line tracing tool for Windows, based on ETW. 项目地址: https://gitcode.com/gh_mirrors/wt/wtrace wtrace是一款基于ETW(Event Tracing for Windows&#xff…

2026/8/2 22:58:03 阅读更多 →

日新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/2 0:00:38 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/2 0:00:38 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/2 0:00:38 阅读更多 →

周新闻

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

最大流算法详解:从水管网络到Ford-Fulkerson与Dinic实战

1. 从水管网络到最大流:一个核心问题的诞生想象一下,你是一个城市供水系统的总工程师。你的城市有多个水源(水库),需要通过一个复杂的地下管道网络,将水输送到各个居民区。每条管道都有其最大通水能力&…

2026/8/2 0:00:38 阅读更多 →
基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

基于Springboot的企业门户网站(源码+LW+调试文档+讲解)

温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)开头有 CSDN 平台…

2026/8/2 0:00:38 阅读更多 →
MATLAB xcorr函数详解:从互相关原理到四大实战应用

MATLAB xcorr函数详解:从互相关原理到四大实战应用

1. 从一次信号“找茬”说起:为什么我们需要互相关几年前,我在处理一组声学传感器数据时遇到了一个棘手的问题。我有两个麦克风记录了一段相同的音频信号,理论上它们接收到的声音波形应该非常相似,只是由于麦克风位置不同&#xff…

2026/8/2 0:00:38 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/2 6:34:16 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/2 2:47:48 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/2 0:23:22 阅读更多 →