c# 学习笔记 - LINQ

1.LINQ概述

1.1 LINQ介绍

 LINQ是语言集查询(Language Integrated Query, LINQ)的查询语言,其集成了c#当中的查询语法,可以通过相同的语法访问不同的数据源.
 我们来看一个一个简单的LINQ查询的语法,LINQ查询语法和我们熟悉SQL查询语句非常相似,从哪个数据源查询from,查询条件where,以及中间的数据处理orderby操作,最后使用select查询即可.

var query = from x in students
	where x.age >= 2
	orderby x.age descending
	select x;
foreach(var x in query) {
    Console.WriteLine(x.age + " " + x.name);
}

 LINQ细节注意

  1. LINQ是一个查询语句,其必须以from子句开头,以select 或 group 子句结束. 在这两个子句之间可以使用where、orderyby、join、let、其他from子句.
  2. LINQ当中的子句from、where、select等都是查询中预定义的关键字。
  3. LINQ查询的执行不是在定义的时候执行,而是在foreach循环访问查询的时候执行查询操作.

1.2 LINQ基本使用

using System.Collections;
class students {
    public int age { get; set; }
    public string name { get; set; }
    public students(int v1, string v2) {
        this.age = v1;
        this.name = v2;
    }
}

class Test {
    static void Main() {
        List<students> students = new List<students>(); // 定义数据源
        students.Add(new students(3, "张三"));
        students.Add(new students(1, "李一"));
        students.Add(new students(2, "王二"));

        var query = from x in students // 定义LINQ查询
                    where x.age >= 2
                    orderby x.age descending
                    select x;
        foreach(var x in query) { // 使用foreach语句执行该查询
            Console.WriteLine(x.age + " " + x.name);
        }
    }
}

/*
3 张三
2 王二
*/

1.3 扩展方法介绍

  介绍
在这里插入图片描述

  1. 在介绍LINQ的扩展方法之前,我们先来了解一下扩展方法的使用,扩展方法是对原有类或者是原有接口实现类的一个扩展,如果我们在这个类或者这个接口实现类上扩展的话,这个类或者是某个接口的实现类都可以拥有对这个方法的使用。
  2. 扩展方法是一种新语法,并且我们需要注意扩展方法的定义 (扩展方法声明在静态类 + 定义为静态方法 + 第一个参数定义扩展类型 + 第一个参数需要添加this )`
// 将方法添加string类当中
static class TestDelegate {
    static void sayHello(this string s, int x, int y) {
        Console.WriteLine("hello wordl....." + x + " " + y);
    }

    static void Main() {
        string s = new string("No hello....");
        s.sayHello(20, 24);
    }
}

// hello wordl.....20 24
public interface IBase { // 接口
    void sayHi();
}

public static class Strengthen { // 接口的实现类上进行扩展 
    public static void sayHello(this IBase ibase) {
        Console.WriteLine("Hello .....");
    }
}

class Achieve : IBase { // 实现类
    public void sayHi() {
        Console.WriteLine("hi .....");
    }
    static void Main() {
        Achieve achieve = new Achieve();
        achieve.sayHi();
        achieve.sayHello();
    }
}
/*
hi .....
Hello .....
*/

1.4 LINQ扩展

  LINQ扩展 – Enumerable扩展介绍
在这里插入图片描述

  1. 在我们使用var变量定义出query查询后,我们使用foreach()去查询这个数据源的时候,因为foreach的底层数据源的查询的时候是需要实现IEnurable<>接口。
  2. 对于这个特性,LINQ为这个IEunerable<>接口提供了各种扩展方法,以此增强我们对LINQ语句的使用.(继承了IEnumerable接口的实现类都可以使用这个扩展语法)(不是关键字where 注意区分)

  LINQ样例举例分析(对于所有实现了IEnumerable接口都可以调用此Where方法)
  LINQ的Where扩展不是对where关键字的扩展,是对于所有实现了IEnumerable接口的一个扩展方法,不是对其本身where关键字,一定要注意这个区别
在这里插入图片描述

这个扩展就是对where关键字的扩展,传入一个实现了IEnumerable接口的实现类,通过了Func<>的一个判断,Fun是一个委托
(传入数据源和整形数据,返回一个bool类型的值的判定)
public class Example {
    public static void Main() {
        List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8};
        
        var query = list.Where((num, index) => num >= 3 && index % 2 == 1); // 利用扩展where完成(大小>=3 索引为奇数)
        foreach(var item in query) {
            Console.WriteLine(item); 
        }
    }
}
// 4 6 8 
public class Example {
    public static void Main() {
        List<int> list = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8};
      
        Func<int, int, bool> predicate = (num, index) => num >= 3 && index % 2 == 1;
        var query = list.Where(predicate);

        foreach(var item in query) {
            Console.WriteLine(item); 
        }
    }
}
// 4 6 8 

1.5 总结

  1. LINQ是C#提供的集成查询语言(namesapce System,LINQ)
  2. LINQ当中有很多已经预定义完成关键字
  3. 为扩展LINQ当中的方法,LINQ有一个Enumerable类用于扩展方法,具体的扩展方式就是通过对方法进行重载,实现多种扩展方式,这样子对于所有实现该接口的类都可以一起使用这些扩展方法。不是对原本的关键字扩展,是对于实现了这些接口的实现类的统一方法的扩展。

2. 标准查询操作符

2.1 筛选(索引、类型筛选…)

 筛选的通用代码(案例只写LINQ查询的关键代码)

using System.Collections;
class students {
    public int age {get; set;}
    public string name {get; set;}
    public students(int v1, string v2){
        this.age = v1;
        this.name = v2;
    }
}


class Test{
    static void Main(){
        List<students> students = new List<students>();
        students.Add(new students(1, "A1"));
        students.Add(new students(2, "B2"));
        students.Add(new students(3, "C3"));
        students.Add(new students(4, "A4"));
        students.Add(new students(5, "B5"));
        students.Add(new students(6, "C6"));

        var query = from r in students
                    where r.age >= 2 && r.age <= 5
                    select r;

        foreach(var x in query) {
            Console.WriteLine(x.name + " " + x.age);
        }

    }
}

 筛选:

// 简单查询
var query = from r in students
	where r.age >= 2 && r.age <= 5
	select r;
	
// 使用了where() 与 select()扩展
var query = students.
	Where(r => r.age >= 2 && r.age <= 5).
	Select(r => r);

 索引筛选:

// 利用Where方法的重载方法扩展实现
var query = students.
    Where((r, index) => index % 2 == 0). // 索引默认从0开始排序
    Select(r => r);
using System.Collections;
class students {
    public int age { get; set; }
    public string name { get; set; }
    public students(int v1, string v2) {
        this.age = v1;
        this.name = v2;
    }
}

class Test {
    static void Main() {
        List<students> students = new List<students>(); // 定义数据源
        students.Add(new students(3, "张三"));
        students.Add(new students(1, "李一"));
        students.Add(new students(2, "王二"));

        var query = from x in students.Where((x, index) => index % 2 == 0)  // Where不是对下面where关键字的扩展
                    where x.name == "张三"
                    orderby x.age descending
                    select x;
        foreach(var x in query) { // 使用foreach语句执行该查询
            Console.WriteLine(x.age + " " + x.name);
        }
    }
}

// 3 张三

 类型筛选:

// 使用OfType()扩展方法,将string类型参数传递给泛型参数
object[] data = { "one", 2, "three", 4, "five", 6 };
var query = data.OfType<string>();
foreach(var item in query) {
    Console.WriteLine(item);
}

2.2 from子句

2.3 orderby排序

2.4 group分组

  GroupBy 扩展方法: Enumerable.GroupBy 方法

/*
GroupBy扩展方法
public static System.Collections.Generic.IEnumerable<System.Linq.IGrouping<TKey,TSource>> 
GroupBy<TSource,TKey> (this System.Collections.Generic.IEnumerable<TSource> source, Func<TSource,TKey> keySelector);
*/
class People {
    public string Name { set; get; }
    public int age { get; set; }

    public People(string name, int age) {
        Name = name;
        this.age = age;
    }
}

class Program {
    static void Main() {
        List<People> list = new List<People>();
        list.Add(new People("张三三", 10));
        list.Add(new People("张杰杰", 20));
        list.Add(new People("张球球", 30));
        list.Add(new People("张非非", 20));
        list.Add(new People("张蹦蹦", 30));

        // GroupBy后数据类型:  System.Collections.Generic.IEnumerable<System.Linq.IGrouping<TKey,TSource>> 
        // 其中内部由多个已经分组好的 System.Linq.IGrouping<TKey, TSource>
        // System.Linq.IGrouping<TKey, TSource> 包含一系列对象以及一个共同的键
        foreach(var item in list.GroupBy(x => x.age) ){ 
            var id = item.Key; // 分组后每个组的 TKey
            Console.WriteLine(id); 

            foreach(var people in item.ToList()) { // item.ToList() 可将分组的 IGrouping 重新组合为 List
                Console.Write(people.Name + " ");
            }
            Console.WriteLine("\n======================");
        }
    }
}
/*
10
张三三
======================
20
张杰杰 张非非
======================
30
张球球 张蹦蹦
======================
*/

2.5 FirstOrDefault

  FirstOrDefault 扩展方法: Enumerable.FirstOrDefault

  • public static TSource? FirstOrDefault (this System.Collections.Generic.IEnumerable source);
    返回序列当中的第一个元素,如果序列当中不包含元素则返回默认值

  • public static TSource FirstOrDefault (this System.Collections.Generic.IEnumerable source, TSource defaultValue);
    返回序列当中的第一个元素,如果序列当中不包含元素则返回指定默认值

  • public static TSource? FirstOrDefault (this System.Collections.Generic.IEnumerable source, Func<TSource,bool> predicate);
    返回序列中满足条件的第一个元素,如果未找到此类元素,则返回默认值。

  • public static TSource FirstOrDefault (this System.Collections.Generic.IEnumerable source, Func<TSource,bool> predicate, TSource defaultValue);
    返回序列中满足条件的第一个元素,如果未找到此类元素,则返回指定的默认值。

static void Main() {
    List<int> list = new List<int>();
    Console.WriteLine(list.FirstOrDefault()); // 为空返回默认值 0
    Console.WriteLine(list.FirstOrDefault(-1)); // 修改其默认值 -1

    int[] x = { 11, 20, 31, 40 };
    list.AddRange(x);
    Console.WriteLine(list.FirstOrDefault(k => k % 10 == 0));  // 20   
    Console.WriteLine(list.FirstOrDefault(k => k % 10 == 5, -1));  // 修改默认值 -1
}
  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

psudd

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值