前言

本文总结学习C#必须知道的基础知识,委托、监视者模式、常用lambda表达式、linq查询,自定义扩展方法,他们之间有什么关系呢?匿名委托是如何演变成lambda表达式,lambda再如何导出linq语句的?

委托

用delegate关键字声明委托,引用MSDN上的一段内容:委托是一种引用方法的类型。一旦为委托分配了方法,委托将与该方法具有完全相同的行为。委托方法的调用可以像其他任何方法一样,具有参数和返回值。

  1. using System;
  2. namespace ConsoleApplication1
  3. {
  4. //这个委托的名字是MyDel,委托的类型是MyDel
  5. //这个委托代表了一系列函数,这一些函数必须是没有返回值,没有参数的
  6. public delegate void MyDel();
  7. //这个委托代表了一系列函数,这一系列函数必须是没有返回值,参数为string类型
  8. public delegate void MyDel2(string name);
  9. //这个委托代表了一系列函数,这一系列函数必须是int类型的返回值,两个int类型的参数
  10. public delegate int MyDel3(int a,int b);
  11. class Program
  12. {
  13. static void Main(string[] args)
  14. {
  15. //创建委托的2种方法
  16. //1.如果使用new关键字创建委托,则必须使用一个函数初始化这个委托对象
  17. MyDel2 my1 = new MyDel2(print);
  18. //2.如果不用new关键字,则可以直接赋值
  19. MyDel2 my2 = print2;
  20. //3.委托和他封装的方法具有相同的功能
  21. my1("ss");
  22. my2("ww");
  23. //4.既然委托代表了一系列函数,那么一个委托对象可以承接多个函数
  24. Console.WriteLine("委托对象承接多个函数");
  25. my1 += print2;
  26. my1("aa");
  27. //5.在承接的函数集中删减函数
  28. Console.WriteLine("委托对象删减函数");
  29. my1 -= print2;
  30. my1("bb");
  31. Console.ReadKey();
  32. }
  33. public static void print(string name) {
  34. Console.WriteLine("print-----------"+name);
  35. }
  36. public static void print2(string n) {
  37. Console.WriteLine("22222-----------"+n);
  38. }
  39. }
  40. }

监视者模式

监视者模式是在微软平台大量存在的一种模式,通俗一点它就是事件,事件就是监视者模式。比如生活中,你睡觉的时候委托同学上课叫醒你,这就是一个监视者模式,你是被监视者,是委托方,同学是被委托方,监视者。下面一个例子是:考试的时候自己委托父母监视自己,考的好的话让父母奖励,考差了则受罚的监视者模式:

  1. using System;
  2. namespace ConsoleApplication1
  3. {
  4. public delegate void Del();
  5. class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. //创建对象
  10. Student s = new Student();
  11. Parent p = new Parent();
  12. //s.p = () => { Console.WriteLine("超常发挥,耶");};
  13. //s.k = () => { Console.WriteLine("考差了,嘤嘤嘤"); };
  14. //学生对象的委托承接着家长对象的方法
  15. s.p += p.PPrice;
  16. s.k += p.KKit;
  17. //s开始执行考试
  18. s.Exam(70);
  19. Console.ReadKey();
  20. }
  21. }
  22. public class Student {
  23. public Del p = null;
  24. public Del k = null;
  25. //执行考试
  26. public void Exam(int f) {
  27. if (f < 60)
  28. {
  29. k();
  30. }
  31. else {
  32. p();
  33. }
  34. }
  35. }
  36. public class Parent {
  37. public void PPrice() {
  38. Console.WriteLine("考的不错,奖励个馒头");
  39. }
  40. public void KKit() {
  41. Console.WriteLine("考的太差,面壁思过");
  42. }
  43. }
  44. }

匿名委托

匿名委托也是一种委托,只不过没有方法名,可以理解为用delegate代替了匿名委托的方法名,很多情况不必要创建方法,需要临时创建方法来调用时使用,下面例子很好的说明匿名委托的不同用法

  1. using System;
  2. namespace ConsoleApplication1
  3. {
  4. public delegate void Delsing();
  5. public delegate int DelPlus(int a,int b);
  6. public delegate string DelString(string a,int b);
  7. class Program
  8. {
  9. static void Main(string[] args)
  10. {
  11. //委托承接命名函数直接执行
  12. Delsing d = Sing;
  13. d();
  14. //匿名委托直接执行
  15. Delsing d1 = delegate() { Console.WriteLine("匿名委托"); };
  16. d1();
  17. //带参数且有返回值的匿名委托,执行后用write方法显示
  18. DelPlus d2 = delegate(int j, int k) { return j + k; };
  19. Console.WriteLine(d2(1,2));
  20. //带参数且有返回值的匿名委托,当做参数来传,然后调用函数实现功能;用定义的其他方法执行委托
  21. DelString d3=delegate(string a,int b){return a+b;};
  22. Test(d3,"1+1=",2);
  23. Console.ReadKey();
  24. }
  25. public static void Test(DelString del, string a, int b) {
  26. string str = del(a,b);
  27. Console.WriteLine(str);
  28. }
  29. public static void Sing() {
  30. Console.WriteLine("I'm singing");
  31. }
  32. }
  33. }

lambda表达式

lambda表达式其实就是匿名委托精简之后的形式,在参数和方法体中补上“=>”(称为goes to)来表示lambda表达式,下面是lambda表达式不同形式的总结

  1. //先定义一个Del开头的委托
  2. public delegate void Del1();
  3. //匿名委托
  4. //转成lambda表达式时要去掉delegate 加上=>
  5. Del1 d1=delegate(){Console.WriteLine("ss");};
  6. d1=()=>{Console.WriteLine("ss");};
  7. //由于没有参数,那么()不能省略
  8. public delegate int Del2();
  9. Del2 d2=delegate(){return 1;};
  10. d2=()=>{return 1;};
  11. //如果是直接返回,换句话说就是没有业务逻辑处理,就是只有一条返回语句,可以把{}换成()同时去掉return关键字
  12. d2=()=>(1);
  13. //如果方法体中有业务逻辑,则必须使用{}
  14. d2=()=>{if(2>1){return 1;}else{return 2;}};
  15. //
  16. public delegate void Del3(string a);
  17. Del3 d3=delegate(string a){Console.WriteLine(a);};
  18. d3=(string a)=>{Console.WriteLine(a);};
  19. //可以把参数的类型去掉,因为系统会自动判断参数的类型,毕竟是把这个lambda赋值给了对应的委托
  20. d3=(a)=>{Console.WriteLine(a);};
  21. //若只有一个参数,则不需要()
  22. d3=a=>{Console.WriteLine(a);};
  23. //
  24. public delegate int Del4(int a,int a);
  25. Del4 d4=delegate(int a,int b){return a+b;};
  26. d4=(int a,int b)=>{return a+b;};
  27. d4=(a,b)=>{return a+b;};
  28. d4=(a,b)=>(a+b);
  29. d4=(a,b)=>a+b;
  30. d5=a=>a+1;

Linq语言集成化查询

linq不同于结构化查询语言(SQL)它不仅可以查询数据而且可以查询对象。

LINQ的官方中文名称为“.NET语言集成查询”,英文全称为“Language-Integrated Query”。它提供了类似于SQL语法的遍历,筛选与投影功能,LINQ不仅能完成对对象的查询,它可以透过DLINQ操作数据库,或是透过XLINQ控制XML。我们来比较一下两个不同方法求出数组中大于20的数据的例子:

  1. using System;
  2. using System.Collections.Generic;
  3. namespace ConsoleApplication2
  4. {
  5. class Program
  6. {
  7. static void Main()
  8. {
  9. int[] a = { 2,23,25,32,5,64,52,30};
  10. //求出数组中大于20的数据
  11. List<int> list = new List<int>();
  12. foreach (int b in a) {
  13. if (b > 20) {
  14. list.Add(b);
  15. }
  16. }
  17. foreach (int c in list) {
  18. Console.WriteLine(c);
  19. }
  20. Console.ReadKey();
  21. }
  22. }
  23. }

2.用IEnumerable的Where扩展方法,通过lambda表达式,精简程序执行过程,需要导入命名空间:using System.Linq;

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace ConsoleApplication2
  5. {
  6. class Program
  7. {
  8. static void Main()
  9. {
  10. int[] a = { 2,23,25,32,5,64,52,30};
  11. //求出数组中大于20的数据
  12. //lambda表达式
  13. //var list = a.Where(p => { return p > 20; });
  14. //简化后 var可以接受任何类型
  15. var list = a.Where(p => p > 20);
  16. //Where 返回类型时IEnumerable
  17. //IEnumerable<int> list = a.Where(p=>p>20);
  18. foreach (int c in list) {
  19. Console.WriteLine(c);
  20. }
  21. Console.ReadKey();
  22. }
  23. }
  24. }

上面可以算是小的LINQ查询,但能算是真正的LINQ,我暂时理解为广义的LINQ。例子中(p=>p>20)其实是一个lambda表达式,是微软定义好的一个委托,从这个委托的特点我们知道它有一个参数,返回值是bool类型。数组肯定实现了IEnumerable接口,而Where是IEnumerable<(Of <T>)>成员的一个扩展方法,MSDN中定义为Where(Func<(Of<(UMP,Boolean)>)>)基于谓词筛选值序列。LINQ查询调用了微软定义好的扩展方法进行查询,下面我们插入一段扩展方法的内容,帮助理解上面LINQ的Where扩展方法。

扩展方法

通俗点说就是在不更改原来类的基础上,为类添加方法。需要注意的是:1.扩展方法必须写在静态类中;2.扩展方法必须是静态方法,虽然是静态方法,但这个扩展方法是为对象扩展的,只能由对象调用。它的定义是:

  1. public static class 类名 {
  2. public static 返回值 方法名(this 要扩展的类型 对象名[,参数列表]) {
  3. }
  4. }

我们来做个扩展方法,为String类型扩展个获取文件类型的方法

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace ConsoleApplication2
  5. {
  6. public class Program
  7. {
  8. public static void Main()
  9. {
  10. //调用扩展方法获取文件类型
  11. string file = @"E:\FTPPUBLISH\学习资料\KindEditor\kindeditor-v4.0.3\examples\colorpicker.html";
  12. Console.WriteLine(file.GetFileType());
  13. string sss = "18.9.06.mp3";
  14. Console.WriteLine(sss.GetFileType());
  15. Console.ReadKey();
  16. }
  17. }
  18. public static class ExtendMethod
  19. {
  20. public static string GetFileType(this string str)
  21. {
  22. string[] strs = str.Split('.');
  23. return strs[strs.Length - 1];
  24. }
  25. }
  26. }

理解了这些扩展方法,相信会有助于你理解上面LINQ查询时所用的Where扩展方法。下面我们继续来看LINQ查询,把上面的LINQ再做一步扩展:

用LINQ语句进行查询,并将结果降序分组排序的三种方式

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. namespace ConsoleApplication2
  5. {
  6. public class Program
  7. {
  8. public static void Main()
  9. {
  10. List<Student> list = new List<Student>();
  11. list.Add(new Student(){Age=10,Name="Jack",Address="bj"});
  12. list.Add(new Student(){Age=67,Name="Mack",Address="郑州"});
  13. list.Add(new Student(){Age=23,Name="Dack",Address="USA"});
  14. list.Add(new Student(){Age=56,Name="Cack",Address="bj"});
  15. list.Add(new Student(){Age=8,Name="Eack",Address="郑州"});
  16. list.Add(new Student(){Age=34,Name="Hack",Address="bj"});
  17. list.Add(new Student(){Age=18,Name="小红",Address="USA"});
  18. Console.WriteLine("查询出集合中年龄大于45的学生");
  19. //查询出集合中年龄大于45的学生(完整形式,一般不这样写)
  20. //Func<Student, bool> f = p => p.Age > 45;
  21. //IEnumerable<Student> result = list.Where<Student>(f);
  22. //简写
  23. var result0 = list.Where<Student>(p=>p.Age>45);
  24. foreach (Student s in result0) {
  25. Console.WriteLine(s.Age+" "+s.Name);
  26. }
  27. Console.WriteLine("查询集合中年龄小于30,并按年龄降序排列,按城市分组");
  28. //查询集合中年龄小于30,并按年龄降序排列,按城市分组
  29. Console.WriteLine("____________________第一种方法____________________");
  30. IEnumerable<Student> result1 = list.Where(p => p.Age < 30).OrderByDescending(p => p.Age);
  31. IEnumerable<IGrouping<string, Student>> result11 = result1.GroupBy<Student, string>(p => p.Address);
  32. foreach (IGrouping<string, Student> gg in result11)
  33. {
  34. foreach (Student s in gg)
  35. {
  36. Console.WriteLine(s.Age + ";" + s.Name + ";" + s.Address);
  37. }
  38. }
  39. Console.WriteLine("____________________第二种方法____________________");
  40. var result2 = list.Where(p => p.Age < 30).OrderByDescending(p => p.Age).GroupBy(p=>p.Address);
  41. //第一次GetEnumerator()得到IEnumerator<IGrouping<string, Student>>
  42. var c = result2.GetEnumerator();
  43. while (c.MoveNext()) {
  44. //第二次GetEnumerator()得到IEnumerator<Student>
  45. var d = c.Current.GetEnumerator();
  46. while (d.MoveNext()) {
  47. //.Current获取集合中位于枚举数当前位置的元素
  48. Console.WriteLine(d.Current.Name+";"+d.Current.Address);
  49. }
  50. }
  51. Console.WriteLine("____________________第三种方法____________________");
  52. var result3 = from p in list
  53. where p.Age < 30
  54. orderby p.Age descending
  55. group p by p.Address;
  56. foreach (var ss in result3) {
  57. foreach (var s in ss) {
  58. Console.WriteLine(s.Age + ";" + s.Name + ";" + s.Address);
  59. }
  60. }
  61. Console.ReadKey();
  62. }
  63. }
  64. public class Student {
  65. public int Age { get; set; }
  66. public string Name { get; set; }
  67. public string Address { get; set; }
  68. }
  69. }

最后我们做个小小的LINQ总结:LINQ语言集成化查询基础是泛型和lambda表达式,它的形式是:

  1. from 元素 in 集合
  2. Where 元素条件
  3. orderby 元素.属性 ascending/descending
  4. group 元素 by 元素.属性
  5. select 元素

和SQL查询类似,上面例子中表明如果使用了groupby语句,则不需要select。

参考资料

本文参考下文,并对文中的例子稍微做了修改

从委托、lambda表达式到linq的一些个人小总结

C#从委托、lambda表达式到linq总结的更多相关文章

  1. entity framework 新手入门篇(1.5)-lambda表达式与linq

    在建立好了EF模型之后,先不着急使用它,在使用它之前,你还需要了解两个相关的技术,lambda表达式与linq. 作为微软C#语言中重要的语法糖-lambda表达式与LINQ,本质都是一个方法,以la ...

  2. c# in deep 之Lambda表达式于LINQ表达式结合后令人惊叹的简洁(2)

    当Lambda表达式和LINQ一起使用时,我们会发现原本冗长的代码会变得如此简单.比如我们要打印0-10之间的奇数,让其从高到低排列并求其平方根,现在只用一行代码即可完成其集合的生成,直接上代码: v ...

  3. C# Lambda表达式和linq表达式 之 匿名对象查询接收

    很多小伙伴都用过Lambda表达式和linq表达式,用起来也得心应手,但是有的小伙伴 对匿名对象的查询与接收比较迷茫,(没有定义相应的实体),怎么在where()里面进行 条件筛选呢?常规用法我就不说 ...

  4. .net学习之新语法学习(匿名类和匿名方法,扩展方法,系统内置委托,Lambda表达式和linq等)

    1.自动属性 Auto-Implemented Properties 2.隐式类型 var  var变量不能作为全局变量使用,因为不能在编译时确定类型 3.参数默认值 和 命名参数 4.对象初始化器 ...

  5. C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询

    1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法 ...

  6. .net Lambda表达式与Linq (LINQ TO object)

    Lambda表达式,是用来写匿名方法的. 在委托用得比较多,因为委托是传递方法的.   定义几个委托: public delegate void DoNoThing();//无参无返回值   publ ...

  7. C#编程 委托 Lambda表达式和事件

    委托 如果我们要把方法当做参数来传递的话,就要用到委托.简单来说委托是一个类型,这个类型可以赋值一个方法的引用. 声明委托 在C#中使用一个类分两个阶段,首选定义这个类,告诉编译器这个类由什么字段和方 ...

  8. C# 基础知识系列- 6 Lambda表达式和Linq简单介绍

    前言 C#的lambda和Linq可以说是一大亮点,C#的Lambda无处不在,Linq在数据查询上也有着举足轻重的地位. 那么什么是Linq呢,Linq是 Language Intergrated ...

  9. 委托 lambda表达式浅显理解

    方法不能跟变量一样当参数传递,怎么办,C#定义了委托,就可以把方法当变量一样传递了,为了简单,匿名方法传递,省得再声明方法了:再简单,lambda表达式传递,比匿名方法更直观. public dele ...

随机推荐

  1. POJ_2941_矩阵

    题目描述: 每组数据给定一个n*n的矩阵,选定不同行不同列的n个元素,求和,若所有选法所产生的和相等,则输出 homogeneous,否则输出not homogeneous. 描述: 数据挺大,爆搜肯 ...

  2. WeChall_Training: Encodings I (Training, Encoding)

    We intercepted this message from one challenger to another, maybe you can find out what they were ta ...

  3. 微信小程序—Flex布局

    参考教程:http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html     https://xluos.github.io/demo/flexb ...

  4. 并发编程的基石——AQS类

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文参考了[Java多线程进阶(六)-- J.U.C之l ...

  5. k8s Pipline CI/CD

    一.Pipeline介绍 pipeline是一套jenkins官方提供的插件,它可以用来在jenkins中实现和集成连续交付 用户可以利用Pipeline的许多功能: 代码:pipeline在代码中实 ...

  6. light oj 1067 费马小定理求逆元

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1067 1067 - Combinations Given n differen ...

  7. REDTEAM 指南---第四章 外部侦察

    第四章 外部侦察 贡献者:Haythem Arfaoui 翻译BugMan 主动侦察 介绍 主动足迹涉及使用可以帮助您收集更多信息的工具和技术 有关目标的信息.与被动足迹不同的是,过程永远不会“触及” ...

  8. docker安装db2数据库

    查询可安装的db2镜像 # docker search db2 [root@docker-servers ~]# docker search db2 INDEX NAME DESCRIPTION ST ...

  9. [Wpf学习] 2.代码导入Xaml

    废话不说,直接上代码 using System.ComponentModel; using System.Runtime.CompilerServices; using System.Windows; ...

  10. Kotlin Tutorials系列文章

    Kotlin Tutorials系列文章 想写一个有实用价值的Kotlin笔记, 让一线开发一看就懂, 看完就能上手. 当然官方文档更有参考价值了. 这个系列相对于官方文档的大而全来说, 最主要优势是 ...