.NET——LINQ(语言集成查询)

为什么要学LINQ,已经学LINQ的好处

LINQ让数据处理变得简单,语言集成查询 (LINQ) 为 C#  提供语言级查询功能和高阶函数 API,让你能够编写具有很高表达力度的声明性代码。(另一种SQL语言)

学习LINQ可以通过这个形式从委托->lambda->LINQ

首先我们先来学习什么是委托

一、委托

什么是委托?

委托是可以指向方法的类型,调用委托遍历时执行的就是遍历指向的方法

在 C#语言中,委托则委托某个方法来实现具体的功能

委托是一种引用类型,虽然在定义委托时与方法有些相似,但不能将其称为方法。

委托在使用时遵循三步走的原则,即定义声明委托、实例化委托以及调用委托。

从数据结构来讲,委托是和类一样是一种用户自定义类型。

委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址。

调用委托的时候,委托包含的所有方法将被执行。

委托是 C# 语言中的一个特色,通常将委托分为命名方法委托、多播委托、匿名委托,其中命名方法委托是使用最多的一种委托。

.NET中定义了泛型委托Action(无返回值),Func(有返回值),所以一般不用自定义委托类型

委托变量不仅可以指向普通方法还可以指向匿名方法

具体的可以参考C#委托(Delegate)简介_c# delegate_小小小陆的博客-CSDN博客

二、lambda表达式

使用Lambda声明运算符=>,从其主体中分离Lambda参数列表。若要创建Lambda表达式,需要在Lambda运算符左侧指定输入参数(如果有参数时),然后在另一侧输入表达式或语句块。
任何Lambda表达式都可以转换为委托类型,可以转换的委托类型由参数和返回值的类型定义。

如果Lambda表达式不返回值,则可以将其转换为Action委托类型之一;否则,可将其转换为Func委托类型之一。例如,有两个参数且不返回值的Lambda表达式可转化为Action<T1, T2>委托。有一个参数且不返回值的Lambda表达式可转换为Func<T, TResult>委托。

匿名方法可以写成lambda表达式

可以省略参数数据类型,因为编译能更具委托类型推断出参数的类型,用=>引出方法体

如果委托没有返回值,且方法体只有一行代码,可省略{}

详尽可参考Lambda表达式详解(C#)_c# lambda表达式详解_草原上唱山歌的博客-CSDN博客

三、LINQ

Linq中提供了很多集合的扩展方法,配合lamdba能简化数据处理

Var类型推断,类型声明

可以使用var让编译器的“类型推断“来简化类型的声明,在Linq中常用

C#的var和JavaScript的var不同,C#是强类型的。

C#中的dynamic是弱类型

C#匿名类型加var,才能发挥var的强大类型

LINQ中提供了大量类似于Where的扩展方法,简化数据处理,大部分都在System.Linq命名空间中。

大部分都是泛型IEnumberable<T>接口的扩展方法

扩展方法是一种在现有类型上添加新方法的机制。在C#中,可以使用扩展方法来为现有的类或接口添加新的方法,而无需修改它们的源代码。

要定义一个扩展方法,需要创建一个静态类,并且这个类必须是在非嵌套、非泛型静态类中定义的。然后,在这个类中定义一个静态方法,该方法是我们要添加的新方法。这个方法的第一个参数必须是要扩展的类型,并且必须使用this关键字作为修饰符。

下面是一个简单的示例,演示了如何为字符串类型添加一个扩展方法来反转字符串:

public static class StringExtensions
{
    public static string Reverse(this string str)
    {
        char[] charArray = str.ToCharArray();
}
}

在LINQ中有很多想SQL里面的各种查询语言

1、where查询语句

Where方法:每一项数据都会经过predicate的测试,如果针对一个元素,predicate指向的返回值为true,那么这个元素就会放到返回值中。

Where参数本质其实是一个lamdba表达式格式的匿名方法,方法的参数e表示当前判断的元素对象。参数的名字不一定非要叫e,不过一般的lamdba表达式中的变量名长度都不长

首先我们需要一些初始数据

List<Employee> list = new List<Employee>();
list.Add(new Employee { ID = 1, Name = "Jerry", Age = 28, Gender = true, Salary = 5000 });
list.Add(new Employee { ID = 2, Name = "Jim", Age = 33, Gender = true, Salary = 3000 });
list.Add(new Employee { ID = 3, Name = "Alice", Age = 51, Gender = false, Salary = 9000 });
list.Add(new Employee { ID = 4, Name = "lucy", Age = 20, Gender = true, Salary = 2000 });
list.Add(new Employee { ID = 5, Name = "kim", Age = 26, Gender = false, Salary = 1000 });
list.Add(new Employee { ID = 6, Name = "lily", Age = 28, Gender = true, Salary = 8000 });
list.Add(new Employee { ID = 7, Name = "zack", Age = 27, Gender = true, Salary = 8500 });
list.Add(new Employee { ID = 8, Name = "mack", Age = 29, Gender = false, Salary = 7000 });

where实例,查询员工中年龄大于20同时薪资大于3000的员工记录,

//where
IEnumerable<Employee> item1 = list.Where(e => e.Age > 20&&e.Salary>3000); 
foreach(Employee item in item1)
{
    Console.WriteLine(item);
}
//count()方法获取符合条件的数据条数
int count1 = list.Count(e => e.Salary > 5000 || e.Age < 30);
Console.WriteLine(count1);
//any至少有一条满足条件,则返回true,没有就返回false
Console.WriteLine(list.Any(e=>e.Salary>30000));

注:IEnumerable接口是C#中的一个接口,用于实现集合的迭代功能。通过实现IEnumerable接口,我们可以使一个类型可迭代,即可以使用foreach循环来遍历该类型的集合元素。其中泛型和LINQ大部分操作都可以基于IEnumber接口操作

在使用where方法的时候还可以与where的另外几个属性组合使用

Single:有且只有一条满足要求的数据;

SingleOrDefault:最多只有一条满足要求的数据;

First:至少有一条,返回第一条

FirstOrDefault:返回第一条或者默认值

实例



//single有且只有一条满足该要求的,多了或者少了都会报错
IEnumerable<Employee> item2= list.Where(e => e.Name == "Jerry");
Employee e1 = item2.Single();
//等同上面两句
//Employee item3 = list.Where(f => f.Name == "Jerry").Single();

Console.WriteLine(e1);


//SingleOrDefault有满足该要求的则返回,如果没有就返回该类型的默认值,如果有多条就报错
Employee e3 = list.SingleOrDefault(e => e.Name == "Jim");//符合该要求则返回
Console.WriteLine(e3);
Employee e4 = list.SingleOrDefault(e => e.Name == "tom");
//一个都没有,返回默认值,默认值是true
Console.WriteLine(e4=null);
int[] nums = new int[] { 3, 5, 8 };
int i = nums.SingleOrDefault(i => i > 7);
Console.WriteLine(i);

//first :至少有一条,返回第一条
//firstordefalut:返回第一条或者默认值;
Employee e5 = list.First(e => e.Age > 30);
Employee e6 = list.FirstOrDefault(e => e.Age == 30);

2、排序语句Order

OrderBy()对数据正序排序

OrderByDescending()倒叙排序

对于简单类型排序,也许不用lamdba表达式。特殊案例:按照最后一个字符排序;用Guid或者随机数进行随机排序。


//OrderBy()对数据正序排序
IEnumerable<Employee> items5 = list.OrderBy(e => e.Age);
foreach(Employee e5 in items5)
{
    Console.WriteLine(e5);
}

//对数据进行正序排序
int[] nums2 = new int[] { 3,9,5,6,10,8,5,7};
IEnumerable<int> nums2 = nums.OrderBy(i => i);
foreach(var i in nums2 )
{
    Console.WriteLine(i);
}

//随机数排序&Guid排序
Random rand = new Random();
var items2 = list.OrderByDescending(e => rand.Next());
//var items2 = list.OrderByDescending(e =>Guid.NewGuid());
foreach (Employee i in items2)
{
    Console.WriteLine(i);
}


//根据字符的最后一个字母排序
var items2 = list.OrderByDescending(e => e.Name[e.Name.Length-1]);
foreach (Employee i in items2)
{
    Console.WriteLine(i);
}


//多种条件组合排序
//先根据年龄排序在和薪资排序
var items2 = list.OrderBy(e => e.Age).ThenByDescending(e => e.Salary);
foreach (Employee i in items2)
{
    Console.WriteLine(i);
}

//限制结果集,获取部分数据
//Skip(n)跳过n条数据,Take(n)获取n条数据。
var item2 = list.Skip(3).Take(2);
foreach(var e in item2)
{
    Console.WriteLine(e);
}

//也可以加上各种限制条件,如果不够则取最多

var items = list.Where(e => e.Age > 25).OrderBy(e=>e.Age).Skip(1).Take(2);
foreach (var e in items)
{
    Console.WriteLine(e);
}
*/

注:Skip,Take也可以单独使用

3、聚合函数:Max();Min();Average();Sum();Count().

Linq中所有的扩展方法几乎都是针对IEnumerable接口的,集合所有能返回的集合都返回IEnumerable,几乎所有方法“链式使用”的。


//聚合函数:Max(); Min(); Average(); Sum(); Count().

//获得年龄最大
int a =list.Max(e=>e.Age);
Console.WriteLine(a);
//ID>6,年龄最大的,组合使用
int f=list.Where(e=>e.ID>6).Max(e=>e.Age);
Console.WriteLine(f);
//比对Name的字符串
string s = list.Max(e => e.Name);
Console.WriteLine(s);
//年龄大于30的平均工资
double c = list.Where(e => e.Age >= 30).Average(e => e.Salary);
Console.WriteLine(c);

聚合函数除了可以单独使用外,还可以和GroupBy()分组函数一起使用


//根据年龄分组,获取每组人数,最高工资,平均工资。用var简化编程

//普通编程
IEnumerable<IGrouping<int ,Employee>> items =list.GroupBy(x => x.Age);
foreach(IGrouping<int ,Employee> g in items)
{
    Console.WriteLine(g.Key);
    foreach(Employee e in g)
    {
        Console.WriteLine(e);
    }
    Console.WriteLine("**************");
}


//用var简化
//sql语句 select age,max(salary) from t group by age
var items = list.GroupBy(x => x.Age);
foreach (IGrouping<int, Employee> g in items)
{
    Console.WriteLine(g.Key);
    Console.WriteLine("最大工资:"+g.Max(e=>e.Salary));
    foreach (Employee e in g)
    {
        Console.WriteLine(e);
    }
    Console.WriteLine("**************");
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值