Linq

一、Lambda 表达式(C# 函数式编程基础)

Lambda 是简化委托(Delegate) 调用的语法糖,让代码更简洁,是 LINQ 的核心语法工具。

  1. 委托是 “方法的引用类型”,可将方法当作参数传递。例如:

    // 声明委托(匹配“接收 int,返回 bool”的方法签名)
    delegate bool MyDelegate(int x);
    // 方法示例
    bool IsEven(int num) => num % 2 == 0;
    // 委托实例化并指向方法
    MyDelegate del = new MyDelegate(IsEven);
    bool result = del(4); // 调用委托,实际执行 IsEven(4)
    
  2. Lambda 表达式写法 用 =>(Lambda 操作符)简化委托的使用,格式为 (参数) => 表达式/语句块

    1. 替代上述委托示例:
    MyDelegate del = x => x % 2 == 0; // 直接用 Lambda 定义“判断偶数”的逻辑
    bool result = del(4); // 结果为 true
    
    1. 多参数 / 语句块示例:
    // 多参数
    Func<int, int, int> add = (a, b) => a + b;
    // 语句块(需用 {} 包裹,且需 return 显式返回)
    Func<int, string> describe = num => {
        if (num > 0) return "正数";
        return "非正数";
    };
    
  3. Lambda 简化规则

    1. 参数类型可省略(编译器自动推断,即 “隐式类型”):
    // 等同于 (int x) => x > 10
    Func<int, bool> isLarge = x => x > 10; 
    
    1. 单个参数可省略括号:
    // 等同于 (x) => x * 2
    Func<int, int> doubleIt = x => x * 2; 
    
    1. 单行表达式可省略 return{}
    // 等同于 num => { return num % 2 == 0; }
    Func<int, bool> isEven = num => num % 2 == 0; 
    
  4. 隐式类型 var 让编译器自动推断变量类型,简化声明。常与 Lambda、LINQ 结合:

  5. 匿名类 无需显式定义类,直接创建 “临时对象”,常用于 LINQ 的投影操作(后文 “9. 投影操作”):

var person = new { Name = "Alice", Age = 25 }; // 匿名类实例
Console.WriteLine(person.Name); // 可直接访问属性
  1. C# 扩展方法 为现有类型(如 stringList<T>)“新增方法”,但无需修改类型源码,是 LINQ 能为 IEnumerable<T> 扩展 Where/Select 等查询方法的核心机制。

    1. 定义示例(为 string 扩展 IsNullOrEmpty 方法):
    public static class StringExtensions {
        public static bool IsNullOrEmpty(this string str) {
            return string.IsNullOrEmpty(str);
        }
    }
    // 使用:
    string s = null;
    bool result = s.IsNullOrEmpty(); // 等价于 string.IsNullOrEmpty(s)
    

二、LINQ(语言集成查询)—— 基于扩展方法的数据查询

LINQ 依托扩展方法和Lambda 表达式,为集合(List<T>、数组等)、数据库、XML 等提供 “统一的查询语法”,核心是对 IEnumerable<T> 接口的扩展。

6.1 数据过滤(Where 方法)

筛选集合中符合条件的元素,返回 IEnumerable<T>

var numbers = new List<int> { 1, 2, 3, 4, 5 };
var evenNumbers = numbers.Where(n => n % 2 == 0); // 结果:[2,4]

6.2 获取数据条数(Count 方法)

统计集合中符合条件的元素数量,返回 int

int count = numbers.Count(n => n > 2); // 结果:3(元素 3、4、5)

6.3 Any 方法使用

判断集合中是否存在符合条件的元素,返回 bool(性能更优,无需遍历全部元素)。

bool hasEven = numbers.Any(n => n % 2 == 0); // 结果:true

6.4 获取一条数据(First/FirstOrDefault/Single 等)

  • First():获取第一个符合条件的元素,无匹配时抛异常;

  • FirstOrDefault():获取第一个符合条件的元素,无匹配时返回类型默认值(如 int 为 0,引用类型为 null);

  • Single():集合中仅有一个符合条件的元素时返回,否则抛异常(用于确保 “唯一结果” 场景)。

int firstEven = numbers.First(n => n % 2 == 0); // 结果:2
int? firstOddOrDefault = numbers.FirstOrDefault(n => n % 2 == 1); // 结果:1

6.5 排序(OrderBy/OrderByDescending

对集合按指定规则升序 / 降序排列,返回排序后的 IEnumerable<T>

var sorted = numbers.OrderBy(n => n); // 升序:[1,2,3,4,5]
var sortedDesc = numbers.OrderByDescending(n => n); // 降序:[5,4,3,2,1]

6.6 限制结果集(Take/Skip

  • Take(n):取前 n 个元素;

  • Skip(n):跳过前 n 个元素,取剩余元素。 常结合使用实现 “分页”。

var top2 = numbers.Take(2); // 结果:[1,2]
var skip2 = numbers.Skip(2); // 结果:[3,4,5]
var page2 = numbers.Skip(2).Take(2); // 跳过前 2 个,取 2 个:[3,4]

6.7 聚合函数(Sum/Min/Max/Average 等)

对集合进行 “聚合计算”,如求和、求最大 / 最小值、平均值等。

int sum = numbers.Sum(); // 结果:15
int max = numbers.Max(); // 结果:5
double avg = numbers.Average(); // 结果:3.0

6.8 分组(GroupBy

将集合按指定键分组,返回 IEnumerable<IGrouping<TKey, TElement>>IGrouping 可理解为 “键 + 分组内元素的集合”。

var people = new List<Person> {
    new Person { Name = "Alice", Age = 25 },
    new Person { Name = "Bob", Age = 30 },
    new Person { Name = "Charlie", Age = 25 }
};
var groupedByAge = people.GroupBy(p => p.Age);
// 遍历分组:
foreach (var group in groupedByAge) {
    Console.WriteLine($"年龄 {group.Key} 的人:");
    foreach (var person in group) {
        Console.WriteLine(person.Name);
    }
}
// 输出:
// 年龄 25 的人:
// Alice
// Charlie
// 年龄 30 的人:
// Bob

6.9 投影操作(Select

将集合中的元素 “转换 / 映射” 为新的形式(如匿名类、其他类型),是 LINQ 中 “数据重塑” 的核心方法。

var names = people.Select(p => p.Name); // 投影为姓名集合:["Alice","Bob","Charlie"]
var anonymous = people.Select(p => new { 
    PersonName = p.Name, 
    AgeCategory = p.Age > 25 ? "年长" : "年轻" 
}); // 投影为匿名类集合

6.10 链式调用

LINQ 方法返回的都是 IEnumerable<T>(或其衍生类型),因此可连续调用多个 LINQ 方法,逐步筛选 / 转换数据。

var result = numbers
    .Where(n => n % 2 == 0)   // 筛选偶数
    .OrderBy(n => n)          // 升序排列
    .Select(n => n * 2)       // 每个数乘 2
    .Take(1);                 // 取第一个
// 结果:4(原偶数 [2,4] → 排序后 [2,4] → 乘 2 后 [4,8] → 取第一个 4)

6.11 LINQ 的另一种写法(查询表达式)

除了 “方法语法”(如 Where/Select 链式调用),LINQ 还支持查询表达式(类似 SQL 语法),编译器会将其转换为方法语法执行。

// 方法语法:
var evenNums1 = numbers.Where(n => n % 2 == 0);
// 查询表达式:
var evenNums2 = from n in numbers
                where n % 2 == 0
                select n;
// 两者完全等价,结果均为 [2,4]

posted on 2025-11-16 16:50  拾玥  阅读(0)  评论(0)    收藏  举报

导航