02020208 .NET Core重难点知识08-常用扩展方法、排序、限制结果集获取部分数据

02020208 .NET Core重难点知识08

1. 常用扩展方法1(视频Part2-17)

  • 本章节笔记中,需要如下元数据
using System;
using System.Collections.Generic;
using System.Linq;

namespace Demo02
{
    class Employee
    {
        public long Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public bool Gender { get; set; }
        public int Salay { get; set; }
        public override string ToString()
        {
            return $"Id = {Id}, Name = {Name}, Age = {Age}, Gender = {Gender}, Salary = {Salay}";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {

            List<Employee> list = new List<Employee>();
            list.Add(new Employee { Id = 1, Name = "jerry", Age = 28, Gender = true, Salay = 5000 });
            list.Add(new Employee { Id = 2, Name = "jim", Age = 33, Gender = true, Salay = 3000 });
            list.Add(new Employee { Id = 3, Name = "lily", Age = 35, Gender = false, Salay = 9000 });
            list.Add(new Employee { Id = 4, Name = "lucy", Age = 16, Gender = false, Salay = 2000 });
            list.Add(new Employee { Id = 5, Name = "kimi", Age = 25, Gender = true, Salay = 1000 });
            list.Add(new Employee { Id = 6, Name = "nancy", Age = 36, Gender = false, Salay = 8000 });
            list.Add(new Employee { Id = 7, Name = "zack", Age = 35, Gender = true, Salay = 8500 });
            list.Add(new Employee { Id = 8, Name = "jack", Age = 33, Gender = true, Salay = 8000 });
        }
    }
}
1.1 LINQ中的扩展方法
  • LINQ中提供了大量类似Where的扩展方法,简化数据处理。大部分都在System.Linq命名空间中。
    • 这些扩展方法,大多数都是对IEnumerable这个泛型接口的扩展。
    • 数组、List、Dictionary、Set...等都是实现了IEnumerable接口的。因此它们都可以使用这些扩展方法的。
1.2 Where方法
  • 每一项数据都会经过predicate的测试,如果针对一个元素,predicate执行的返回值为true,那么这个元素就会放到返回值中。
  • Where参数是一个Lambda表达式格式的匿名方法,方法的参数e表示当前判断的元素对象。参数的名字不一定非要叫做e,不过一般Lambda表达式中的变量名长度都不长。
static void Main(string[] args)
{
    ...
    IEnumerable<Employee> items = list.Where(e => e.Age > 30);
    foreach (Employee it in items)
    {
        Console.WriteLine(it);
    }

    Console.ReadLine();
}
1.3 Count方法
  • Count方法用于获取数据条数。
static void Main(string[] args)
{
    ...
    IEnumerable<Employee> items = list.Where(e => e.Age > 30);
    Console.WriteLine(list.Count());
    Console.WriteLine(items.Count());
    Console.WriteLine(list.Count(e => e.Age > 20));
    Console.WriteLine(list.Count(e => e.Age > 20 && e.Salay > 8000));
    Console.ReadLine();
}

控制台输出:
8
5
7
2
1.4 Any方法
  • Any方法用于判断是否至少有一条数据。
static void Main(string[] args)
{
    ...
    IEnumerable<Employee> items = list.Where(e => e.Age > 30);
    Console.WriteLine(list.Any());
    Console.WriteLine(items.Any());
    Console.WriteLine(list.Any(e => e.Age > 20 && e.Salay > 10000));
    Console.ReadLine();
}

控制台输出:
True
True
False

说明:Count方法会将满足条件的数据都读出来,而Any只要触发了条件就可以。因此Any有可能比Count效率更高。

2. 常用扩展方法2(Part2-18)

  • 获取一条数据(是否带参数的两种写法)
    • Single → 有且只有一条满足要求的数据。
      • SingleOrDefault → 最多只有一条满足要求的数据。
    • First → 至少有一条,返回第一条数据。
      • FirstOrDefault → 返回第一条或者默认值。
  • 选择合适的方法,防御性编程。
2.1 Single方法
  • 有且只有一条数据
// Single方法 → 有多条数据抛出异常
static void Main(string[] args)
{
    ...
    Employee e1 = list.Single();
    Console.WriteLine(e1);

    Console.ReadLine();
}

异常信息:System.InvalidOperationException:“Sequence contains more than one element”

说明:Single表示有且只有一条数据,如果有多条数据,那么抛出异常。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → 有且只有一条
static void Main(string[] args)
{
    ...
    Console.WriteLine(list.Where(e => e.Name == "jerry").Single()); // @1
    Console.ReadLine();
}

控制台输出:
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000

说明:在@1处(list.Where(e => e.Name == "jerry"),返回的是一个可迭代的数据,因此可以直接用Single()方法判断。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → Where返回的是一个可迭代对象,可以直接用Single方法。
static void Main(string[] args)
{
    ...
    Console.WriteLine(list.Where(e => e.Name == "Qinway").Single()); 
    Console.ReadLine();
}

异常信息:System.InvalidOperationException:“Sequence contains no elements”

说明:Single方法,如果没有数据,也会抛出异常。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → Lambda表达式作为参数
static void Main(string[] args)
{
    Employee e2 = list.Single(e => e.Name == "jim");
    Console.WriteLine(e2);
}

控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
2.2 SingleOrDefault方法
  • 最多只有一条满足要求的数据,即可以有一条,也可以没有。
// Singel方法 → 最多一条,可以没有。
static void Main(string[] args)
{
    Console.WriteLine(list.SingleOrDefault(e => e.Name == "jim")); // 有一条数据,返回。
    Console.ReadLine();
}

控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → 如果一条数据都没有,对于值类型返回0,对于引用类型返回null。
static void Main(string[] args)
{
    Employee e2 = list.SingleOrDefault(e => e.Name == "Qinway"); // 没有数据,对于引用类型,返回null。
    Console.WriteLine(e2 == null); // → True

    int[] nums = new int[] { 1, 3, 6 };
    int e3 = nums.SingleOrDefault(e => e > 10); // 没有数据,对于值类型,返回0。
    Console.WriteLine(e3); // → 0
    Console.ReadLine();
}

控制台输出:
True
0
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// Single方法 → 有多条,抛出异常。
static void Main(string[] args)
{
    Console.WriteLine(list.SingleOrDefault(e => e.Age > 20));
}

异常信息:System.InvalidOperationException:“Sequence contains more than one matching element”
2.3 First方法
  • 至少有一条,返回第一条。
// First方法 → 有多条,返回第一条。
static void Main(string[] args)
{
    Employee e2 = list.First(e => e.Age > 30);
    Console.WriteLine(e2);
    Console.ReadLine();
}

控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000

说明:数据源从上往下数,遇到第一个就返回该数据。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// First方法 → 如果一个都没有,抛出异常。
static void Main(string[] args)
{
    Employee e2 = list.First(e => e.Age > 50); // 抛出异常。
    Console.WriteLine(e2);

    Console.ReadLine();
}

异常信息:System.InvalidOperationException:“Sequence contains no matching element”
2.4 FirstOrDefault
  • 返回第一条或者默认值,可以没有,如果有返回第一个。
static void Main(string[] args)
{
    Employee e1 = list.FirstOrDefault(e => e.Age > 30); // 有多条,返回第一条。
    Console.WriteLine(e1);
    Employee e2 = list.FirstOrDefault(e => e.Age > 50); // 一条没有,返回默认值。
    Console.WriteLine(e2 == null); // → True
    Console.ReadLine();
}

控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
True
2.5 总结
  • 上述方法灵活运用,用合适的方法提前筛选并抛出异常。让异常提前暴露出来,及早发现,及早处理。有防御性编程的思维。

3. 排序

  • Order方法 → 对数据正序排序。
  • OrderByDescending方法 → 倒序排序。
list.OrderBy(e = e.Age);

说明:
1. 对于简单类型排序,可以用自身排序。
2. 特殊案例:按照最后一个字符排序,用Guide或者随机数进行随机排序。
3.1 正序、倒序、随机排序
// 对引用类型进行排序
static void Main(string[] args)
{
    IEnumerable<Employee> items1 = list.OrderBy(e => e.Age);
    foreach (Employee it in items1)
    {
        Console.WriteLine(it);
    }
    Console.WriteLine("**********************************");
    IEnumerable<Employee> items2 = list.OrderByDescending(e => e.Age);
    foreach (Employee it in items2)
    {
        Console.WriteLine(it);
    }
    Console.ReadLine();
}

控制台输出:
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
**********************************
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000

说明:OrderBy返回的是IOrderedEnumerable<T>泛型接口,IOrderedEnumerable又继承自IEnumerable<T>泛型接口,因此可以用foreach遍历。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 对值类型进行排序
static void Main(string[] args)
{
    int[] nums = new int[] { 10, 3, 1, 12, 6 };
    IEnumerable<int> num1 = nums.OrderBy(e => e); // 注意这里Lambda表达式对应的匿名方法delegate (int e) {return e;},表示用自身排序
    foreach (int n in num1)
    {
        Console.WriteLine(n);
    }

    Console.ReadLine();
}

控制台输出:
1
3
6
10
12
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 使用NewGuid方法,进行随机排序。
static void Main(string[] args)
{
    var items = list.OrderBy(e => Guid.NewGuid()); // NewGuid方法生成一个随机值,对这个随机值进行排序。
    foreach (var it in items)
    {
        Console.WriteLine(it);
    }

    Console.ReadLine();
}

控制台输出:
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 使用Random随机数排序
static void Main(string[] args)
{
    Random rd = new Random();
    var items = list.OrderBy(e => rd.Next()); // 通过随机数进行排序
    foreach (var it in items)
    {
        Console.WriteLine(it);
    }
    Console.ReadLine();
}

控制台输出:
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 根据Name最后一个字符进行排序
static void Main(string[] args)
{
    var items = list.OrderBy(e => e.Name[e.Name.Length-1]); 
    foreach (var it in items)
    {
        Console.WriteLine(it);
    }

    Console.ReadLine();
}

控制台输出:
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
总结:排序表达式可以随意写。
3.2 多规则排序
  • 可以在Order(),OrderByDecending()后继续写ThenBy()、ThenByDecending()。
// 示例:优先按照Age排序,如果Age相同在按照Salary排序。
list.OrderBy(e => e. Age).ThenByDecending(e => e.Salary)

注意:千万不要写成list.OrderBy(e => e. Age).OrderBy(e => e.Salary)
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 按年龄从小到大排序,然后工资从大到小排序
static void Main(string[] args)
{
    var items = list.OrderBy(e => e.Age).ThenByDescending(e => e.Salay);
    foreach (var it in items)
    {
        Console.WriteLine(it);
    }
    Console.ReadLine();
}

控制台输出:
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000

4 限制结果集,获取部分数据

  • skip(n) → 跳过n条数据,Taken(n)获取n条数据。
var orderedItems = list.Skip(2).Taken(3); // 跳过2条,取3条。

说明:Skip()、Take()也可以单独使用。
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 跳过2条,获取3条数据
static void Main(string[] args)
{
    var orderedItems = list.Skip(2).Take(3); 
    foreach (var it in orderedItems)
    {
        Console.WriteLine(it);
    }
    Console.ReadLine();
}

控制台输出:
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 跳过4条,取所有数据
static void Main(string[] args)
{
    var orderedItems = list.Skip(4);
    foreach (var it in orderedItems)
    {
        Console.WriteLine(it);
    }
    Console.ReadLine();
}

控制台输出:
Id = 5, Name = kimi, Age = 25, Gender = True, Salary = 1000
Id = 6, Name = nancy, Age = 36, Gender = False, Salary = 8000
Id = 7, Name = zack, Age = 35, Gender = True, Salary = 8500
Id = 8, Name = jack, Age = 33, Gender = True, Salary = 8000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 取4条数据,后面不要
static void Main(string[] args)
{
    var orderedItems = list.Take(4);
    foreach (var it in orderedItems)
    {
        Console.WriteLine(it);
    }
    Console.ReadLine();
}

控制台输出:
Id = 1, Name = jerry, Age = 28, Gender = True, Salary = 5000
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000
Id = 4, Name = lucy, Age = 16, Gender = False, Salary = 2000
—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—·—
// 添加过滤条件
static void Main(string[] args)
{
    var orderedItems = list.Where(e => e.Age > 30).Take(2); // 先获取年龄大于30的,然后取2条。
    foreach (var it in orderedItems)
    {
        Console.WriteLine(it);
    }
    Console.ReadLine();
}

控制台输出:
Id = 2, Name = jim, Age = 33, Gender = True, Salary = 3000
Id = 3, Name = lily, Age = 35, Gender = False, Salary = 9000

结尾

书籍:ASP.NET Core技术内幕与项目实战

视频:https://www.bilibili.com/video/BV1pK41137He

著:杨中科

ISBN:978-7-115-58657-5

版次:第1版

发行:人民邮电出版社

※敬请购买正版书籍,侵删请联系85863947@qq.com※

※本文章为看书或查阅资料而总结的笔记,仅供参考,如有错误请留言指正,谢谢!※

posted @ 2025-08-30 20:18  qinway  阅读(1)  评论(0)    收藏  举报