Lambda(Linq)

在谈到lambda表达式之前,首先要说一下委托,在下一章会详细介绍委托,在这里就是简单说明一下。

委托的关键字段delegate,声明委托

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

可以这样说吧,委托就好比于在C语言中的函数指针。

在这里先声明一个无返回值的DoNothing方法

        private void DoNothing(int id, string name)
        {
            Console.WriteLine("{0} {1} DoNothing out",id,name);
        }

要使用委托必须方法签名相一致。

在框架1.0时代。

                NoReturnWithPara method = new NoReturnWithPara(this.DoNothing);//2 委托的实例化
                method.Invoke(1, "ming");//3 委托的调用
                method(2, "22");
 method.Invoke(1, "ming");和 method(2, "22");效果是一样的。后来随着版本的升级,又发生了一点变化,可以把new对象给省略。
                NoReturnWithPara method = this.DoNothing;
                method.Invoke(2, "jia");

 但是这样的写法,微软爸爸又觉得这样写不太方便,因为这样写需要提前准备个DoNothing方法,所以微软做了个大的修改,这回改的居然可以把DoNothing也省略,这就很方便了,没记错的话这应该是发生在框架3.0时代

                    NoReturnWithPara method = new NoReturnWithPara(
                    delegate(int id, string name)//把方法的声明改成了使用delegate关键字
                    {

                        Console.WriteLine("{0} {1} DoNothing",id,name);
                    });
                method.Invoke(3, "yy");

  这样写已经很便利了吧,但是“懒才是社会进步的动力”,为了偷懒,微软居然把delegate关键字也省略,改为=>(goes to)。

               NoReturnWithPara method = new NoReturnWithPara(
                                 (int id, string name) =>//goes to
                                 //lambda表达式:是一个匿名方法,是一个方法
                                 {
                                     Console.WriteLine(nameOut);
                                     Console.WriteLine("{0} {1} DoNothing");
                                 });
               method.Invoke(4, "N");

  已经到达这样了,但是人类还是不满足,后来索性把参数类型也省略,因为你要是这个委托,那肯定必须满足委托的参数类型

                NoReturnWithPara method = new NoReturnWithPara(
                                     (id, name) =>
                                     //去掉参数类型,原因是委托的约束
                                     {
                                         Console.WriteLine("{0} {1} DoNothing",id,name);
                                     });
                method.Invoke(5, "小小");

  都到这个地步了,我们还是可以偷偷懒的,只是需要满足几个条件。

1)如果方法体只有一行,那么可以去掉大括号和分号,多行不行
2)如果参数只有一个 可以去掉小括号
3)如果没有参数,直接用小括号

            {
              NoReturnWithPara method = new NoReturnWithPara((id, name) => Console.WriteLine("{0} {1} DoNothing", id, name));
                method.Invoke(6, "分");
             }

那么什么是 匿名类 和var关键字。

                  var model = new
                    {
                        Id = 1,
                        Name = " Go",
                        Age = 21,
                        ClassId = 2
                    };
                    Console.WriteLine(model.Id);
                    Console.WriteLine(model.Name);

var:它主要用于在声明变量时,无法确定数据类型时使用

就好比这个model,他的类型是不确定的,这就可以声明匿名类。

再来讲讲系统自带委托Action/Func。

Action是无返回值类型的委托,Func是带有返回值类型的委托。

                Action act1 = () => Console.WriteLine("1234");
                Action<int> act2 = t => { };
                Func<int> func1 = () => 1;
                int i = func1();
                Func<int, string> func2 = t => "1234";

什么是拓展方法呢。在这里我就不讲官方的语言了,就讲讲我的认识吧,其实拓展方法在我看来就是一些静态方法,在你调用这个方法时,不需要去创建一个对象,直接可以调用。

那么怎么去创建一个拓展方法呢,其实很简单,主要是声明一个静态类,在静态类里面声明一个静态方法,方法的第一个参数声明一个对象,注意第一个参数类型前面加上this

        public static void NoShow(this LambdaShow show)
        {
            Console.WriteLine("这里是扩展的 NoShow");
        }
                    LambdaShow show = new LambdaShow();
                    show.Show();
                    show.NoShow();

那万一类方法中有一个show方法,而拓展方法里面也有一个show方法,那通过show.Show();调用是调用类里面的方法还是拓展里面的方法呢?答案是类中的方法。

接下来再来谈谈linq。在这里我就简单的说下linq几个常用的方法吧。

创建一个student实体类

 public class Student
    {

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

初始化实体类,并添加一些数据。

 private List<Student> GetStudentList()
        {

            List<Student> studentList = new List<Student>()
            {
                new Student()
                {
                    Id=1,
                    Name="猎人",
                    ClassId=2,
                    Age=35
                },
                new Student()
                {
                    Id=1,
                    Name=" Go",
                    ClassId=2,
                    Age=23
                },
                 new Student()
                {
                    Id=1,
                    Name="水",
                    ClassId=2,
                    Age=27
                },
                 new Student()
                {
                    Id=1,
                    Name="明",
                    ClassId=2,
                    Age=26
                }
      }

在这里提出一个需求,筛选出年龄大于25岁的同学。

如果不适用linq只使用普通方法,大概是思路是先创建一个student的list对象,然后再把实体对象遍历判断条件,条件满足的添加到list集合中。

            List<Student> studentList = this.GetStudentList();

            List<Student> studentListlessThan25 = new List<Student>();
            foreach (var item in studentList)
            {
                if (item.Age < 25)
                {
                    studentListlessThan25.Add(item);
                }
            }

而如果我们使用Linq呢

               var list = studentList.Where<Student>(s => s.Age < 25);
                foreach (var item in list)
                {
                    Console.WriteLine("Name={0}  Age={1}", item.Name, item.Age);
                }

如果你熟悉的话,这样看语句就跟看陈述句一样简单明了。

那么我们不经要问,框架的where函数里面封装了哪些方法呢,让我们使用起来这么简单。通过反编译工具,其实里面的方法很简单

模仿者框架中的where方法,试着自己写了一个方法。

 public static IEnumerable<TSource> XiMaWhere<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> func)
        {
            List<TSource> studentList = new List<TSource>();
            foreach (TSource item in source)
            {
                bool bResult=func.Invoke(item);
                if (bResult)
                {
                    studentList.Add(item);
                }
            }
            return studentList;
        }

这就是where方法里面主要的一些内容

然后我们可以跟where方法一样使用

               var list = studentList.XiMaWhere<Student>(s => s.Age < 25);//陈述句

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

是不是很强大!!!

还有一些linq语句,这里就简单带过一下,有兴趣的可以自己去查阅资料

               Console.WriteLine("********************");
                var list = from s in studentList
                           where s.Age < 25
                           select s;

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

  

时间: 2024-10-27 02:11:05

Lambda(Linq)的相关文章

C#标准查询运算(Linq)

1.标准查询符 在C#3.0之后微软对集合进行了非常大的改造,使用了查询符进行集合的查询,这一切都来自.NetFramework 对Lambda表达式的支持.标准查询符,一共有两种类型是支持泛型和不支持泛型的,因为引入泛型的目的在于写出公用的代码,避免代码累赘. 注意,除非赋值给变量的类型是一眼就能看出来的,否则就应该只有在声明类型的时候指定隐式类型的变量(var). 在System.Linq.Enumerable命名空间下面有很多的标准出阿仙奴符号,通过这些查询符号可以减少程序中重复写for循

遇见C++ Lambda(转)

生成随机数字 假设我们有一个vector<int>容器,想用100以内的随机数初始化它,其中一个办法是通过generate函数生成,如代码1所示.generate函数接受三个参数,前两个参数指定容器的起止位置,后一个参数指定生成逻辑,这个逻辑正是通过Lambda来表达的. 代码 1 我们现在看到Lambda是最简形式,只包含捕获子句和函数体两个必要部分,其他部分都省略了.[]是Lambda的捕获子句,也是引出Lambda的语法,当编译器看到这个符号时,就知道我们在写一个Lambda了.函数体通

[C/C++]如何给Lambda(匿名)函数命名?

C++11增加了Lambda(匿名)函数,在实际使用中发现对匿名函数命名是很有必要的(增强代码阅读性). 本文介绍一种优雅的方法实现对匿名函数的命名. 我发现,任何增强代码阅读性而且又不违反编译器规则的方式都是定义空定义,比如: /**  * MFC框架内标识消息处理函数的宏,没有实际意义,  * 但是一眼就能看出这是消息处理函数.  */  #ifndef afx_msg  #define afx_msg         // intentional placeholder  #endif /

filter,map,reduce,lambda(python3)

1.filter filter(function,sequence) 对sequence中的item依次执行function(item),将执行的结果为True(符合函数判断)的item组成一个list.string.tuple(根据sequence类型决定)返回. 1 #!/usr/bin/env python 2 # encoding: utf-8 3 """ 4 @author: 侠之大者kamil 5 @file: filter.py 6 @time: 2016/4/

初识Java8新特性Lambda(三 ) 之lambda类库Stream

简介 Java SE 8 增加了新的语言特性(例如 lambda 表达式和默认方法),为此 Java SE 8 的类库也进行了很多改进,本文简要介绍了这些改进.在阅读本文前,你应该先阅读 深入浅出Java 8 Lambda(语言篇),以便对 Java SE 8 的新增特性有一个全面了解. 背景(Background) 自从lambda表达式成为Java语言的一部分之后,Java集合(Collections)API就面临着大幅变化.而 JSR 355(规定了 Java lambda 表达式的标准)

初识Java8新特性Lambda(二) 之collections

背景(Background) 如果从一开始就将lambda表达式(闭包)作为Java语言的一部分,那么我们的Collections API肯定会与今天的外观有所不同.随着Java语言获得作为JSR 335一部分的lambda表达式,这具有使我们的Collections接口看起来更加过时的副作用.尽管可能很想从头开始并构建替换的Collection框架(" Collections II"),但是替换Collection框架将是一项主要任务,因为Collections接口遍布JDK库.相反

C#第六次作业(LINQ)

LINQ,语言集成查询(Language Integrated Query)是一组用于C#和Visual Basic语言的扩展.它允许编写C#或者Visual Basic代码以查询数据库相同的方式操作内存数据. LINQ可以对多种数据源和对象进行查询,如数据库.数据集.XML文档甚至是数组,这在传统的查询语句中是很难实现的.如果有一个集合类型的值需要进行查询,则必须使用Where等方法进行遍历,而使用LINQ可以仿真SQL语句的形式进行查询,极大的降低了难度. 数组中的数据可以被LINQ查询语句

函数编程——匿名函数与lambda(一)

python允许用lambda关键字创造匿名函数. 匿名函数是因为不需要以标准的方式来声明,比如说,使用def语句. 但是,作为函数,它们也能有参数. 一个完整的lambda"语句"代表了一个表达式,这个表达式的定义体必须和声明放在同一行. 参数时可选的,如果使用参数的话,参数通常也是表达式的一部分. 核心知识点: 用合适的表达式调用一个lambda生成一个可以像其他函数一样使用的函数对象. 它们可以被传给其他函数,用额外的引用别名化,作为容器对象以及可调用的对象被调用.(如果需要,可

实战 EF(LINQ) 如何以子查询的形式来 Join

如题,大多数网上关于 LINQ Join 的示例都是以 from x in TableA  join ... 这样的形式,这种有好处,也有劣势,就是在比如我们使用的框架如果已经封装了很多方法,比如分页方法.而我们的业务方法只需要在 Service 层调用框架的分页方法,同时注入条件拼接的委托就可以了.而这时候,为了简单,就会以调用 Join() 方法来实现关联查询,外部看起来好像是子查询,而实际上 Entity Framework 生成 SQL 时,还是会以 Inner join 的形式来生成