Linq的学习

这里继续使用之前文章创建的学生类,首先简单介绍一下linq的使用。

Student.cs

 public class Student
{
public int Id { get; set; }
public int ClassId { get; set; } public string Name { get; set; } public int Age { get; set; } public string Description { get; set; } public void Study()
{
Console.WriteLine($"{this.Id} {this.Name} 跟着老师学习 .Net开发"); } public void StudyQt()
{
Console.WriteLine($"{this.Id} {this.Name} 跟着老师学习C++ Qt");
}
}

初始化学生数据

public class LinqPrinciple
{
private List<Student> GetStudentsList()
{
List<Student> students = new List<Student>()
{ new Student() { Id = 1, ClassId = 1, Name = "张三", Age = 20, Description = "张三是一个好学生" },
new Student() { Id = 2, ClassId = 1, Name = "李四", Age = 21, Description = "李四是一个好学生" },
new Student() { Id = 3, ClassId = 2, Name = "王五", Age = 22, Description = "王五是一个好学生" },
new Student() { Id = 4, ClassId = 2, Name = "赵六", Age = 23, Description = "赵六是一个好学生" },
new Student() { Id = 5, ClassId = 3, Name = "孙七", Age = 24, Description = "孙七是一个好学生" },
new Student() { Id = 6, ClassId = 3, Name = "周八", Age = 25, Description = "周八是一个好学生" },
new Student() { Id = 7, ClassId = 1, Name = "绿春", Age = 30, Description = "张三是一个好学生" },
new Student() { Id = 8, ClassId = 1, Name = "麻醉", Age = 35, Description = "李四是一个好学生" },
new Student() { Id = 9, ClassId = 2, Name = "开天", Age = 26, Description = "王五是一个好学生" },
new Student() { Id = 10, ClassId = 2, Name = "匹敌", Age = 22, Description = "赵六是一个好学生" },
new Student() { Id = 11, ClassId = 3, Name = "独轮车", Age = 23, Description = "孙七是一个好学生" },
new Student() { Id = 12, ClassId = 3, Name = "火箭英", Age = 20, Description = "周八是一个好学生" } };
return students;
}
}

下面写几个简单的linq的语句,大概知道一下它的使用.


public void Show()
{
//获取一下ClassID为3的学生们
List<Student> students = GetStudentsList();
List<Student> studentsId=students.Where(s => s.ClassId == 3).ToList();
Console.WriteLine("********************************1*****************************");
foreach (var student in studentsId)
{
Console.WriteLine($"{student.Id} {student.Name} {student.Age} {student.Description}");
}
Console.WriteLine("********************************2*****************************");
//获取一下年纪大于24的学生们
List<Student> studentsAge = students.Where(s => s.Age > 24).ToList();
foreach (var student in studentsAge)
{
Console.WriteLine($"{student.Id} {student.Name} {student.Age} {student.Description}");
}
Console.WriteLine("********************************3*****************************");
//获取一下年纪小于23同时ClassID为2的学生们
List<Student> studentsAgeClassId = students.Where(s => s.Age < 23 && s.ClassId == 2).ToList();
foreach (var student in studentsAgeClassId)
{
Console.WriteLine($"{student.Id} {student.Name} {student.Age} {student.Description}");
}
}

linq的原理的探究

下面尝试探索一下这个linq的本质是什么?

尝试自己实现一下这3个需求代码,如下

 List<Student> students = GetStudentsList();
List<Student> studentsId=new List<Student>();
foreach (var student in students)
{
if (student.ClassId == 3)
{
studentsId.Add(student);
}
} List<Student> studentsAge=new List<Student>();
foreach (var student in students)
{
if (student.Age > 24)
{
studentsAge.Add(student);
}
} List<Student> studentsAgeClassId=new List<Student>();
foreach (var student in students)
{
if (student.Age < 23 && student.ClassId == 2)
{
studentsAgeClassId.Add(student);
}
}

这上面的代码有什么问题?

大量的重复代码---最好是封装一些,把重复的代码统一封装;

这里使用一个解决方案

封装一个方法,将判断的逻辑独立到一个小方法中去.

        public static bool  IsOk01(Student student)
{
return student.ClassId == 3;
} public static bool IsOk02(Student student)
{
return student.Age > 24;
} public static bool IsOk03(Student student)
{
return student.Age < 23 && student.ClassId == 2;
}
public static List<Student> DragonWhere(List<Student> studentlist,Func<Student,bool> Func)
{
List<Student> students = new List<Student>();
foreach (var student in studentlist)
{
if (Func(student))
{
students.Add(student);
}
}
return students;
}

尝试使用一下封装的函数

List<Student> students = GetStudentsList();
List<Student> studentId= MethodExtension.DragonWhere(students, MethodExtension.IsOk01);

这里还可以使用扩展方法和lambda表达式进一步的优化我们的代码

      public static List<Student> DragonWhere(this List<Student> studentlist,Func<Student,bool> Func)
{
List<Student> students = new List<Student>();
foreach (var student in studentlist)
{
if (Func(student))
{
students.Add(student);
}
}
return students;
}

在调用的时候,

List<Student> students = GetStudentsList();
List<Student> studentsId = students.DragonWhere(s => s.ClassId == 3);

这里就串联上了我们之前学到的知识,最后为了支持多种数据类型,使用上泛型,最后我们就得到了最终封装的方法.

 public static List<T> DragonWhere<T>(this List<T> studentlist,Func<T,bool> Func)
{
List<T> students = new List<T>();
foreach (var student in studentlist)
{
if (Func(student))
{
students.Add(student);
}
}
return students;
}

这里也要使用ilspy反编译一下它们的实现是如何?

看起来跟我们自己实现的Where差不多的样子.

再去看一下它的movenext函数.

这个就是一个yield return反汇编出来的状态机的代码。

linq常见的语句

 public void Show()
{
List<Student> studentList = this.GetStudentList();
#region Linq 扩展方法&表达式
{
var list = studentList.Where<Student>(s => s.Age < 30); //list里面必然是符合要求的数据;
foreach (var item in list)
{
Console.WriteLine("Name={0} Age={1}", item.Name, item.Age);
}
}
{
Console.WriteLine("********************");
var list = from s in studentList
where s.Age < 30
select s; //list里面必然是符合要求的数据; foreach (var item in list)
{
Console.WriteLine("Name={0} Age={1}", item.Name, item.Age);
}
}
#endregion #region linq to object Show
{
Console.WriteLine("********************");
var list = studentList.Where<Student>(s => s.Age < 30)
.Select(s => new //投影:可以做一些自由组装+ new 一个匿名类,也可以new 具体类;
{
IdName = s.Id + s.Name,
ClassName = s.ClassId == 2 ? "高级班" : "其他班"
});
foreach (var item in list)
{
Console.WriteLine("Name={0} Age={1}", item.ClassName, item.IdName);
}
}
{
Console.WriteLine("********************");
var list = from s in studentList
where s.Age < 30
select new
{
IdName = s.Id + s.Name,
ClassName = s.ClassId == 2 ? "高级班" : "其他班"
}; foreach (var item in list)
{
Console.WriteLine("Name={0} Age={1}", item.ClassName, item.IdName);
}
}
{
Console.WriteLine("********************");
var list = studentList.Where<Student>(s => s.Age < 30)//条件过滤
.Select(s => new//投影
{
Id = s.Id,
ClassId = s.ClassId,
IdName = s.Id + s.Name,
ClassName = s.ClassId == 2 ? "高级班" : "其他班"
})
.OrderBy(s => s.Id)//排序 升序
.ThenBy(s => s.ClassName) //多重排序,可以多个字段排序都生效
.OrderByDescending(s => s.ClassId)//倒排
.Skip(2)//跳过几条 //必须要先排序
.Take(3)//获取几条 //必须要先排序
;
foreach (var item in list)
{
Console.WriteLine($"Name={item.ClassName} Age={item.IdName}");
}
}
{//group by·
Console.WriteLine("********************");
var list = from s in studentList
where s.Age < 30
group s by s.ClassId into sg
select new
{
key = sg.Key,
maxAge = sg.Max(t => t.Age)
};
foreach (var item in list)
{
Console.WriteLine($"key={item.key} maxAge={item.maxAge}");
}
//group by new {s.ClassId,s.Age}
//group by new {A=s.ClassId>1}
}
{
Console.WriteLine("********************");
var list = studentList.GroupBy(s => s.ClassId).Select(sg => new
{
key = sg.Key,
maxAge = sg.Max(t => t.Age)
});
foreach (var item in list)
{
Console.WriteLine($"key={item.key} maxAge={item.maxAge}");
}
}
{
var list = studentList.GroupBy(s => s.ClassId);
foreach (var date in list) ///实现了IEnumerable
{
Console.WriteLine(date.Key); foreach (var item in date)
{
Console.WriteLine(item.Age);
} } }
List<Class> classList = new List<Class>()
{
new Class()
{
Id=1,
ClassName="架构班"
},
new Class()
{
Id=2,
ClassName="高级班"
},
new Class()
{
Id=3,
ClassName="全栈班"
},
};
{ //Join
var list = from s in studentList
join c in classList on s.ClassId equals c.Id //只能使用equals 不能使==
select new
{
Name = s.Name,
CalssName = c.ClassName
};
foreach (var item in list)
{
Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
}
}
{
var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new
{
Name = s.Name,
CalssName = c.ClassName
});
foreach (var item in list)
{
Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
}
}
{//左连接
var list = from s in studentList
join c in classList on s.ClassId equals c.Id
into scList
from sc in scList.DefaultIfEmpty()//
select new
{
Name = s.Name,
CalssName = sc == null ? "无班级" : sc.ClassName//c变sc,为空则用
};
foreach (var item in list)
{
Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
}
Console.WriteLine(list.Count());
}
{
var list = studentList.Join(classList, s => s.ClassId, c => c.Id, (s, c) => new
{
Name = s.Name,
CalssName = c.ClassName
}).DefaultIfEmpty();//为空就没有了
foreach (var item in list)
{
Console.WriteLine($"Name={item.Name},CalssName={item.CalssName}");
}
Console.WriteLine(list.Count());
}
{ //左连接和右链接 就是链接对象交换一下即可; }
#endregion
}

Csharp学习Linq的更多相关文章

  1. LinqPad工具:帮你快速学习Linq

    LinqPad工具:帮你快速学习Linq 参考: http://www.cnblogs.com/li-peng/p/3441729.html ★:linqPad下载地址:http://www.linq ...

  2. 白话LINQ系列2---以代码演进方式学习LINQ必备条件

    今天,我们通过一个简单的示例代码的演进过程,来学习LINQ必备条件:隐式类型局部变量:对象集合初始化器:委托:匿名函数:lambda表达式:扩展方法:匿名类型.废话不多说,我们直接进入主题. 一.实现 ...

  3. 学习LINQ,发现一个好的工具。LINQPad!!

    今日学习LINQ,发现一个好的工具.LINQPad!! 此工具的好处在于,不需要在程序内执行,直接只用工具测试.然后代码通过即可,速度快,简洁方便. 可以生成其LINQ查询对应的lambda和SQL语 ...

  4. 学习LINQ必备条件

    转自:http://www.cnblogs.com/VolcanoCloud/p/4451302.html 学习LINQ必备条件:隐式类型局部变量:对象集合初始化器:委托:匿名函数:lambda表达式 ...

  5. js_html_input中autocomplete="off"在chrom中失效的解决办法 使用JS模拟锚点跳转 js如何获取url参数 C#模拟httpwebrequest请求_向服务器模拟cookie发送 实习期学到的技术(一) LinqPad的变量比较功能 ASP.NET EF 使用LinqPad 快速学习Linq

    js_html_input中autocomplete="off"在chrom中失效的解决办法 分享网上的2种办法: 1-可以在不需要默认填写的input框中设置 autocompl ...

  6. 用linqPad帮助你快速学习LINQ

    在这里我向大家推荐的一个具是LinqPad有了这个工具并熟练使用就可以很快学习并掌握linq linqPad下载地址:http://www.linqpad.net/ 它也自带了很多例子方便大家查询,l ...

  7. linqPad快速学习LINQ(含视频)

    在这里我向大家推荐的一个具是LinqPad有了这个工具并熟练使用就可以很快学习并掌握linq 安装步骤: 使用LINQPad可以很方便的调试linq以及lambda表达式.其中自带了linq以及F#简 ...

  8. C#深度学习のLINQ

    一.LINQ的由来 LINQ是Language Integrated Query的缩写,意思是语言扩展查询 查询是一种从数据源检索数据的表达式. 查询通常用专门的查询语言来表示. 随着时间的推移,人们 ...

  9. ASP.NET EF 使用LinqPad 快速学习Linq

    使用LinqPad这个工具可以很快学习并掌握linq[Language Integrated Query] linqPad官方下载地址:http://www.linqpad.net/ linqPad4 ...

  10. 学习Linq之前必须知道的几种语法糖

         » 引用百度解释: 语法糖(Syntactic sugar),也译为糖衣语法,是由英国计算机科学家彼得·约翰·兰达(Peter J. Landin)发明的一个术语,指计算机语言中添加的某种语 ...

随机推荐

  1. P1405 苦恼的小明 题解

    题目传送门 前置知识 扩展欧拉定理 解法 本题幂塔是有限层的,这里与 luogu P4139 上帝与集合的正确用法 中的无限层幂塔不同,故需要在到达递归边界 \(n+1\) 时进行特殊处理,对于处理 ...

  2. 从函数柯里化聊到add(1)(2)(3) add(1, 2)(3),以及柯里化无限调用

    壹 ❀ 引 很久之前看到过的一道面试题,最近复习又遇到了,这里简单做个整理,本题考点主要是函数柯里化,所以在实现前还是简单介绍什么是柯里化. 贰 ❀ 函数柯里化(Currying) 所谓函数柯里化,其 ...

  3. NC19995 [HAOI2015]树上操作

    题目链接 题目 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权. 然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子 ...

  4. Linux 中竖线“|”与双竖线“||”的意思

    linux中竖线'|',双竖线'||',&和&&的意思 对于初学者来说这几个意思可能只知道其中几个的意思,下面我们来看一下. 1.竖线'|' ,在linux中是作为管道符的,将 ...

  5. NVME学习笔记杂谈—名词定义

    1.5 定义1.5.1 Admin QueueAdmin Queue 是标识符为 0 的 Submission Queue 和 Completion Queue .Admin Submission Q ...

  6. 【Flink入门修炼】1-4 Flink 核心概念与架构

    前面几篇文章带大家了解了 Flink 是什么.能做什么,本篇将带大家了解 Flink 究竟是如何完成这些的,Flink 本身架构是什么样的,让大家先对 Flink 有整体认知,便于后期理解. 一.Fl ...

  7. Mybatis的缓存过期机制和RedisCache

    MyBatis的缓存过期机制, flushInterval参数 在实际测试中, 发现Redis中的缓存数据TTL为-1, 在Hash中的key也无过期时间信息, 怀疑RedisCache的实现是否能正 ...

  8. 树莓派/Linux ubuntu 开机自动改网络mac地址(主要适用于拷贝内存卡的情况/不同树莓派mac地址不同)

    树莓派/Linux ubuntu 开机自动改网络mac地址(主要适用于拷贝内存卡的情况/不同树莓派mac地址不同) yaml文件名根据自己原卡中名字更改 address=$(cat /sys/clas ...

  9. win32 - 将原始音频样本转换为wav文件

    需要先从麦克风中采样,代码样本可以参考官方示例: WASAPI Capture Shared Event Driven 官方示例采样10s, 我们需要在WriteWaveFile函数下添加生成原始音频 ...

  10. 美团面试:说说OOM三大场景和解决方案? (绝对史上最全)

    首先,咱们先聊聊,什么是OOM? 小伙伴们,有没有遇到过程序突然崩溃,然后抛出一个OutOfMemoryError的异常?这就是我们俗称的OOM,也就是内存溢出.简单来说,就是你的Java应用想要的内 ...