前言

本文总结学习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. [python之路]格式化显示

    格式化显示 格式规范微语言 中文版 以下整理自 python字符串格式化 *输出结果的空格在md预览中没效果(用代码块三个撇号就可以保留格式了) 一.使用格式化符来格式化字符串: Python支持的所 ...

  2. Codeforces_490_E

    http://codeforces.com/problemset/problem/490/E dfs,过程要注意细节,特别是当前位置取了与上个数当前位置相同是,若后面不符合条件,则当前位置要重置'?' ...

  3. js变量和函数提升

    写在前面: 变量提升是 声明提升,初始化不会提升,比如说 var a=1; console.log(a); 实际是这样执行(个人理解,仅供参考) var a; console.log(a); a=1; ...

  4. TensorFlow中使用GPU

    TensorFlow默认会占用设备上所有的GPU以及每个GPU的所有显存:如果指定了某块GPU,也会默认一次性占用该GPU的所有显存.可以通过以下方式解决: 1 Python代码中设置环境变量,指定G ...

  5. React+wangeditor+node富文本处理带图片上传

    最近有个需求出现在我的视野中,因为我的另外的博客需要上传文章,但是我不想每次都在我的数据库中慢慢的修改格式,所以我另做了一个后台去编辑文本后发送给服务器,那么这里就涉及到两点,一个是富文本,一个是需要 ...

  6. java6循环结构二

    public class jh_01_回顾与作业点评 { public static void main(String[] args) { int val = 12345; System.out.pr ...

  7. sqlserver install on linux chapter two

    The previous chapter is tell us how to install sqlerver on linuix Today, we will see how to make it ...

  8. DRF框架的安装与使用

    目录 DRF框架的安装与配置 基于restful接口规范的接口设计 DRF框架的安装与配置 """ 1)安装 >: pip install djangorestfr ...

  9. php面试笔记(3)-php基础知识-运算符

    本文是根据慕课网Jason老师的课程进行的PHP面试知识点总结和升华,如有侵权请联系我进行删除,email:guoyugygy@163.com 在面试中,考官往往喜欢基础扎实的面试者,而运算符相关的考 ...

  10. Java架构师必看,超详细的架构师知识点分享!

    在Java程序员行业中,有不少Java开发人员的理想是成为一名优秀的Java架构师,Java架构师的主要任务不是从事具体的软件程序的编写,而是从事更高层次的开发构架工作.他必须对开发技术非常了解,并且 ...