Lambda表达式的本质是匿名函数

时间:2023-12-17 15:52:50

1.委托的简介:

委托可以简单的理解为方法的列表,添加的方法的参数类型,个数,顺序必须和委托一致,

也就是说委托起到了托管方法的作用,并且约束了要调用的方法.

         //1声明委托
         public delegate void NoReturnNoPara();
         public delegate void NoReturnWithPara(string name, int id);
         public delegate int WithReturnNoPara();
         public delegate string WithReturnWithPara(string name);

基础代码:

         private void ShowPerson(string name, int id)
         {
             Console.WriteLine("this is id={0} name={1}", id, name);
         } 

ShowPerson

     public class Student
     {
         public int Id { get; set; }
         public int ClassId { get; set; }
         public string Name { get; set; }
         public int Age { get; set; }

         public void Study()
         {
             Console.WriteLine("正在学习高级班");
         }
     }

     /// <summary>
     /// 班级
     /// </summary>
     public class Class
     {
         public int Id { get; set; }
         public string Name { get; set; }
     }

Student

           {
                 Student student = new Student()
                 {
                     Id = ,
                     ClassId = ,
                     Name = "Courage-dhj"
                 };
                 student.Study();

                 var people = new //匿名类
                 {
                     Id = ,
                     ClassId = ,
                     Name = "Courage-dhj"
                 };
                 Console.WriteLine("{0} {1} {2}", people.Id, people.Name, people.ClassId);
             }

匿名类

             {
                 NoReturnWithPara method = new NoReturnWithPara(ShowPerson);//2 实例化委托
                 method.);//3 委托调用
                 ShowPerson();//方法的普通调用
             }

2.匿名方法:      用delegate代替了方法名而已(修饰符和返回类型这里看作方法名)

            {
                 NoReturnWithPara method = new NoReturnWithPara(
                     delegate(string name, int id)
                     {
                         Console.WriteLine("this is id={0} name={1}", id, name);
                     });//匿名方法
                 method.);
             }

3.Lambda表达式

            {
                 NoReturnWithPara method = new NoReturnWithPara(
                     (string name, int id) =>
                     {
                         Console.WriteLine("this is id={0} name={1}", id, name);
                     });//lambda表达式  把delegate换成箭头
                 method.Invoke();
                 //lambda表达式的本质就是一个匿名方法,,也就是一个方法
             }

因为委托对方法有约束作用,所以,方法的参数类型可以省略

          {
                 NoReturnWithPara method = new NoReturnWithPara(
                                    (name, id) =>//lambda表达式方法主体只有一行,可以去掉大括号和分号
                                        Console.WriteLine("this is id={0} name={1}", id, name)
                                    );
                 method.Invoke();
             }

其他的形式:

           {
                 NoReturnWithPara method = new NoReturnWithPara(
                                    (name, id) =>//lambda表达式方法主体只有一行,可以去掉大括号和分号
                                        Console.WriteLine("this is id={0} name={1}", id, name)
                                    );
                 method.Invoke();
             }
            {
                //new一个委托的时候,可以简写
                NoReturnWithPara method = (name, id) => Console.WriteLine("this is id={0} name={1}", id, name);//常用的形式
                method.Invoke();
            }

4.  Action 和  Func----这是系统自带的委托,方便我们使用.

4.1-Action-无返回值的委托---看下面的in也看的出来啦!

先查看系统代码的说明:


 namespace System
 {
     // 摘要:
     //     封装一个方法,该方法不具有参数并且不返回值。
     [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
     public delegate void Action();
 }

Action(一个参数)


 namespace System
 {
     // 摘要:
     //     封装一个方法,该方法只有一个参数并且不返回值。
     //
     // 参数:
     //   obj:
     //     此委托封装的方法的参数。
     //
     // 类型参数:
     //   T:
     //     此委托封装的方法的参数类型。
     public delegate void Action<in T>(T obj);
 }

Action(in T)

  namespace System
    {
        // 摘要:
        //     封装一个方法,该方法具有 16 个参数并且不返回值。
        //
        // 参数:
        //   arg1:
        //     此委托封装的方法的第一个参数。
        //
       //   arg2:
       //     此委托封装的方法的第二个参数。
       //
       //   arg3:
       //     此委托封装的方法的第三个参数。
       //
       //   arg4:
       //     此委托封装的方法的第四个参数。
       //
       //   arg5:
       //     此委托封装的方法的第五个参数。
       //
       //   arg6:
       //     此委托封装的方法的第六个参数。
       //
       //   arg7:
       //     此委托封装的方法的第七个参数。
       //
       //   arg8:
       //     此委托封装的方法的第八个参数。
       //
       //   arg9:
       //     此委托封装的方法的第九个参数。
       //
       //   arg10:
       //     此委托封装的方法的第十个参数。
       //
       //   arg11:
       //     此委托封装的方法的第十一个参数。
       //
       //   arg12:
       //     此委托封装的方法的第十二个参数。
       //
       //   arg13:
       //     此委托封装的方法的第十三个参数。
       //
       //   arg14:
       //     此委托封装的方法的第十四个参数。
       //
       //   arg15:
       //     此委托封装的方法的第十五个参数。
       //
       //   arg16:
       //     此委托封装的方法的第十六个参数。
       //
       // 类型参数:
       //   T1:
       //     此委托封装的方法的第一个参数类型。
       //
       //   T2:
       //     此委托封装的方法的第二个参数类型。
       //
       //   T3:
       //     此委托封装的方法的第三个参数类型。
       //
       //   T4:
       //     此委托封装的方法的第四个参数类型。
       //
       //   T5:
       //     此委托封装的方法的第五个参数的类型。
       //
       //   T6:
       //     此委托封装的方法的第六个参数的类型。
       //
       //   T7:
       //     此委托封装的方法的第七个参数的类型。
       //
       //   T8:
       //     此委托封装的方法的第八个参数的类型。
       //
       //   T9:
       //     此委托封装的方法的第九个参数的类型。
       //
       //   T10:
       //     此委托封装的方法的第十个参数的类型。
       //
       //   T11:
       //     此委托封装的方法的第十一个参数的类型。
       //
       //   T12:
       //     此委托封装的方法的第十二个参数的类型。
       //
       //   T13:
       //     此委托封装的方法的第十三个参数的类型。
       //
       //   T14:
       //     此委托封装的方法的第十四个参数的类型。
       //
       //   T15:
       //     此委托封装的方法的第十五个参数的类型。
      //
      //   T16:
      //     此委托封装的方法的第十六个参数的类型。
      public delegate void Action<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
  }

系统封装-最多16个参数

实例化:

             //接受0到16个参数的  无返回值 泛型委托
             Action act1 = () => Console.WriteLine(
             Action<
             Action<Student, Class, 

4.2.  Func---有返回值---看out就看得出来啦!

 namespace System
 {
     // 摘要:
     //     封装一个不具有参数但却返回 TResult 参数指定的类型值的方法。
     //
     // 类型参数:
     //   TResult:
     //     此委托封装的方法的返回值类型。
     //
     // 返回结果:
     //     此委托封装的方法的返回值。
     [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
     public delegate TResult Func<out TResult>();
 }

无参数,有一个返回值

 namespace System
 {
     // 摘要:
     //     封装一个具有一个参数并返回 TResult 参数指定的类型值的方法。
     //
     // 参数:
     //   arg:
     //     此委托封装的方法的参数。
     //
     // 类型参数:
     //   T:
     //     此委托封装的方法的参数类型。
     //
     //   TResult:
     //     此委托封装的方法的返回值类型。
     //
     // 返回结果:
     //     此委托封装的方法的返回值。
     [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=Neutral, PublicKeyToken=b77a5c561934e089")]
     public delegate TResult Func<in T, out TResult>(T arg);
 }

一个in,一个out

 namespace System
 {
     // 摘要:
     //     封装一个方法,该方法具有 16 个参数,并返回 TResult 参数所指定的类型的值。
     //
     // 参数:
     //   arg1:
     //     此委托封装的方法的第一个参数。
     //
     //   arg2:
     //     此委托封装的方法的第二个参数。
     //
     //   arg3:
     //     此委托封装的方法的第三个参数。
     //
     //   arg4:
     //     此委托封装的方法的第四个参数。
     //
     //   arg5:
     //     此委托封装的方法的第五个参数。
     //
     //   arg6:
     //     此委托封装的方法的第六个参数。
     //
     //   arg7:
     //     此委托封装的方法的第七个参数。
     //
     //   arg8:
     //     此委托封装的方法的第八个参数。
     //
     //   arg9:
     //     此委托封装的方法的第九个参数。
     //
     //   arg10:
     //     此委托封装的方法的第十个参数。
     //
     //   arg11:
     //     此委托封装的方法的第十一个参数。
     //
     //   arg12:
     //     此委托封装的方法的第十二个参数。
     //
     //   arg13:
     //     此委托封装的方法的第十三个参数。
     //
     //   arg14:
     //     此委托封装的方法的第十四个参数。
     //
     //   arg15:
     //     此委托封装的方法的第十五个参数。
     //
     //   arg16:
     //     此委托封装的方法的第十六个参数。
     //
     // 类型参数:
     //   T1:
     //     此委托封装的方法的第一个参数类型。
     //
     //   T2:
     //     此委托封装的方法的第二个参数类型。
     //
     //   T3:
     //     此委托封装的方法的第三个参数类型。
     //
     //   T4:
     //     此委托封装的方法的第四个参数类型。
     //
     //   T5:
     //     此委托封装的方法的第五个参数的类型。
     //
     //   T6:
     //     此委托封装的方法的第六个参数的类型。
     //
     //   T7:
     //     此委托封装的方法的第七个参数的类型。
     //
     //   T8:
     //     此委托封装的方法的第八个参数的类型。
     //
     //   T9:
     //     此委托封装的方法的第九个参数的类型。
     //
     //   T10:
     //     此委托封装的方法的第十个参数的类型。
     //
     //   T11:
     //     此委托封装的方法的第十一个参数的类型。
     //
     //   T12:
     //     此委托封装的方法的第十二个参数的类型。
     //
     //   T13:
     //     此委托封装的方法的第十三个参数的类型。
     //
     //   T14:
     //     此委托封装的方法的第十四个参数的类型。
     //
     //   T15:
     //     此委托封装的方法的第十五个参数的类型。
     //
     //   T16:
     //     此委托封装的方法的第十六个参数的类型。
     //
     //   TResult:
     //     此委托封装的方法的返回值类型。
     //
     // 返回结果:
     //     此委托封装的方法的返回值。
     public delegate TResult Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, out TResult>(T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16);
 }

系统最多16个in参数

不过,不管怎么变,Func的最后一个始终都时out,因为它时有返回值的呗!

 //注意:这是一个新的类型,类型的不同包括了参数的个数的哦.
  public delegate TResult ;
     Func<in T1, in T2, in T3, in T4, in T5, in T6, in T7, in T8, in T9, in T10, in T11, in T12, in T13, in T14, in T15, in T16, in T17, out TResult>
     (T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9,
     T10 arg10, T11 arg11, T12 arg12, T13 arg13, T14 arg14, T15 arg15, T16 arg16, T17 arg17);

如果16个参数不够的话

 //接受0到16个参数的  带返回值 泛型委托
             Func<int> func1 = () => DateTime.Now.Millisecond;//4--返回int类型        //下面都返回string类型
             Func<
             Func<Student, Class,
             //调用自己写的,17个参数
             Func<Student, Student, Class, 

5  扩展方法:  静态类的静态方法第一个参数加上 this.(静态类不一定要加上static,只要有静态方法的类就是静态类)

     /// <summary>
     /// 静态类的静态方法,第一个参数前面加上this
     /// </summary>
     public static class ExtendTest
     {
         /// <summary>
         /// 转成int  失败给0写日志
         /// </summary>
         /// <param name="sNumber"></param>
         /// <returns></returns>
         public static int ToInt(this string sNumber)
         {
             ;
             if (int.TryParse(sNumber, out iNumber))
             {
                 return iNumber;
             }
             else
             {
                 Console.WriteLine("{0} 转换失败,给出默认值", sNumber);
                 ;
             }
         }

         public static void Study(this Student student)
         {
             Console.WriteLine(");
         }

         public static void StudyVip(this Student student)
         {
             Console.WriteLine(");
         }

         public static void ConsoleShow(this object oValue)
         {
             Console.WriteLine(oValue);
         }

     }

调用:  就像给某个类添加了一个方法一样,所以才叫扩展方法啊!

           ";
                 ExtendTest.ToInt(sNumber);//普通调用--返回一个int
                 sNumber.ToInt();//扩展方法调用--返回一个int

                 Student student = new Student()
                 {
                     Name = "天道无情(387-天道无情-男)"
                 };
                 student.StudyVip();
                 student.Study();
                 student.ConsoleShow();

不过,扩展方法并非给this 修饰的类添加了一个方法,而是通过this添加了一个纽带.

当我们调用扩展方法时,还是进入了我们自己写的方法里.

只不过它看起来像时我们给一个类注入了一个方法而已.(这里用注入很形象的形容)

记住:扩展方法时写在一个外部的静态类里,并且是一个静态方法,参数类型前加this.

6. Linq 查询

         private static List<Student> GetStudentList()
         {
             #region 初始化数据
             List<Student> studentList = new List<Student>()
             {
                 new Student()
                 {
                     Id=,
                     Name="Answer(学委-answer-男)",
                     Age=,
                     ClassId=
                 },
                 new Student()
                 {
                     Id=,
                     Name=" LTS_信仰I(196-LTS_信仰I-男-深圳)",
                     Age=,
                     ClassId=
                 },
                 new Student()
                 {
                     Id=,
                     Name="ObjectIsNotFound",
                     Age=,
                     ClassId=
                 },
                 new Student()
                 {
                     Id=,
                     Name="落单的候鸟",
                     Age=,
                     ClassId=
                 },
                 new Student()
                 {
                     Id=,
                     Name="夜的乐章",
                     Age=,
                     ClassId=
                 },
                 new Student()
                 {
                     Id=,
                     Name="知心dě朋友=(357-杰仔-男-广州)",
                     Age=,
                     ClassId=
                 },
                 new Student()
                 {
                     Id=,
                     Name="我",
                     Age=,
                     ClassId=
                 },
                 new Student()
                 {
                     Id=,
                     Name="小逸",
                     Age=,
                     ClassId=
                 },
                   new Student()
                 {
                     Id=,
                     Name="季雨林",
                     Age=,
                     ClassId=
                 },
                   new Student()
                 {
                     Id=,
                     Name="dean",
                     Age=,
                     ClassId=
                 },
                    new Student()
                 {
                     Id=,
                     Name="yup_h",
                     Age=,
                     ClassId=
                 }
             };
             #endregion 初始化数据
             return studentList;
         }

Linq用到的数据

普通程序员一般会想的方法:

             List<Student> studentList = GetStudentList();
             {
                 List<Student> targetList = new List<Student>();
                 foreach (var item in studentList)
                 {
                     )
                     {
                         targetList.Add(item);
                     }
                 }
             }

Linq查询和Lambda表达式查询:

 //
         // 摘要:
         //     基于谓词筛选值序列。
         //
         // 参数:
         //   source:
         //     要筛选的 System.Collections.Generic.IEnumerable<T>。
         //
         //   predicate:
         //     用于测试每个元素是否满足条件的函数。
         //
         // 类型参数:
         //   TSource:
         //     source 中的元素的类型。
         //
         // 返回结果:
         //     一个 System.Collections.Generic.IEnumerable<T>,包含输入序列中满足条件的元素。
         //
         // 异常:
         //   System.ArgumentNullException:
         //     source 或 predicate 为 null。
         public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

Where

注:Where本身是一个扩展方法.

Lambda

            {
                 Console.WriteLine("**************************");
                 );//陈述式
                 foreach (var item in targetList)
                 {
                     Console.WriteLine(" {0}  {1}", item.Age, item.Name);
                 }
                 Console.WriteLine("**************************");
 

Linq

                 Console.WriteLine("**************************");
                 var list = from s in studentList

                            select s;
                 foreach (var item in list)
                 {
                     Console.WriteLine(" {0}  {1}", item.Age, item.Name);
                 }

为了弄懂原理,请看下面:

7.    Lambda查询模拟器:

this IEnumerable<TSource> source 是数据源

Func<TSource, bool> predicate 是查找的方法,第一个参数是传入参数in,后一个是返回类型-用于判断.

    public static class ElevenExtend
     {
         public static IEnumerable<TSource> ElevenWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
         {
             if (source == null) throw new Exception("null");

             List<TSource> tList = new List<TSource>();

             foreach (var item in source)
             {
                 if (predicate.Invoke(item)) //调用时会返回一个bool
                     tList.Add(item);
             }
             return tList;
         }
     }
         private static bool CheckStudentAge(Student student)
         {
             ;
         }

调用:

      Func<Student, bool> func = new Func<Student, bool>(CheckStudentAge); //t => t.Age > 25;
         var targetListEleven = studentList.ElevenWhere<Student>(func);//陈述式
          foreach (var item in targetListEleven)
          {
               Console.WriteLine(" {0}  {1}", item.Age, item.Name);
          }

8. 其他的查询:

            {
                 Console.WriteLine("**************************");
                  || t.Name.Contains(,  }.Contains(t.ClassId));//陈述式
                 foreach (var item in targetList)
                 {
                     Console.WriteLine(" {0}  {1}", item.Age, item.Name);
                 }
             }
         //
         // 摘要:
         //     将序列中的每个元素投影到新表中。
         //
         // 参数:
         //   source:
         //     一个值序列,要对该序列调用转换函数。
         //
         //   selector:
         //     应用于每个元素的转换函数。
         //
         // 类型参数:
         //   TSource:
         //     source 中的元素的类型。
         //
         //   TResult:
         //     selector 返回的值的类型。
         //
         // 返回结果:
         //     一个 System.Collections.Generic.IEnumerable<T>,其元素为对 source 的每个元素调用转换函数的结果。
         //
         // 异常:
         //   System.ArgumentNullException:
         //     source 或 selector 为 null。
         public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector); 

Select投影查询

        {
                 var list = studentList.Select(s => new
                                       {
                                           IdAge = string.Format("{0}_{1}", s.Id, s.Age),
                                           Name = s.Name
                                       });
                 Console.WriteLine("**************************");
                 foreach (var student in list)
                 {
                     Console.WriteLine("Name={0} Age={1}", student.Name, student.IdAge);
                 }
             }

对应的linq

        {
                 var list = from student in studentList
                            //
                            select new
                            {
                                IdAge = string.Format("{0}_{1}", student.Id, student.Age),
                                Name = student.Name
                            };//语法糖

                 Console.WriteLine("**************************");
                 foreach (var student in list)
                 {
                     Console.WriteLine("Name={0} Age={1}", student.Name, student.IdAge);
                 }
             }
       {
                 Console.WriteLine("**************************");
                  && s.Id < )
                                                    .Select<Student, Student>(s =>             //Skip是跳过  Take是获取                                        new Student { Age = s.Age, Name = string.Format("{0}_{1}", s.Name, s.Id) })
                                                    .OrderBy<Student, int>(s => s.Id)
                                                    .OrderByDescending<Student, int>(s => s.Age)
                                                    .Skip<Student>()//跳过1个
                                                    .Take<Student>())//获取5个
                 {
                     Console.WriteLine("Name={0} Age={1}", student.Name, student.Age);
                 }
             }

注:linq查询编译后还是调用的Lambda表达式.