zoukankan      html  css  js  c++  java
  • Lamda演变历史

    • .NetFramework 1.0  1.1时代

    以前学习委托,大部分流程都是在这里声明委托,实例化的时候不得不声明一个方法,在写一个方法不得不传进入,这个方法与声明的委托参数返回值吻合,然后把这个方法传递进去。

    namespace LamdaHistory
    {
        public static class NetFramework1
        {
            public delegate void NoReturnNoPara();//声明委托
            public delegate void NoReturnWithPara(int x, string y);//声明委托
            public static void Show()
            {
                NoReturnNoPara method = new NoReturnNoPara(DoNothing);
                method.Invoke();
    
                NoReturnWithPara method2 = new NoReturnWithPara(Study);
                method2.Invoke(123, "董小姐");
            }
    
            private static void DoNothing()
            {
                Console.WriteLine("This is DoNothing");
            }
    
            private static void Study(int id, string name)
            {
                Console.WriteLine($"{id} {name} 学习.Net高级班");
            }
        }
    }

    如下图所示委托编译后从IL层面看就是一个密封的,且其继承自MulticastDelegete的类

    • .NetFramework 2.0

    1、不在像以前老老实实写方法名称,而是把方法体直接写在实例化委托这里了,前面加关键字delegate,匿名方法没有名字

    2、可以访问局部变量age,如果像1.0时代,是个方法的话,没有办法访问到局部变量age

    namespace LamdaHistory
    {
        public static class NetFramework2
        {
            public delegate void NoReturnNoPara();//声明委托
            public delegate void NoReturnWithPara(int x, string y);//声明委托
            public static void Show()
            {
                int age = 20;
                NoReturnNoPara method = new NoReturnNoPara(delegate {
                    Console.WriteLine("This is DoNothing");
                });
                method.Invoke();
    
                NoReturnWithPara method2 = new NoReturnWithPara(delegate(int id,string name) {
                    Console.WriteLine($"{id} {name} {age} 学习.Net高级班");
                });
                method2.Invoke(123, "董小姐");
            }
        }
    }
    • .NetFramework3.0

    1、把delegate关键字去掉,增加了一个箭头,箭头念goes to,这就是Lamda表达式参数列表=>方法体

    amespace LamdaHistory
    {
        public static class NetFramework3
        {
            public delegate void NoReturnNoPara();//声明委托
            public delegate void NoReturnWithPara(int x, string y);//声明委托
            public static void Show()
            {
                int age = 20;
                NoReturnNoPara method = new NoReturnNoPara(()=> {
                    Console.WriteLine("This is DoNothing");
                });
                method.Invoke();
    
                NoReturnWithPara method2 = new NoReturnWithPara((int id,string name) => {
                    Console.WriteLine($"{id} {name} {age} 学习.Net高级班");
                });
                method2.Invoke(123, "董小姐");
    
                //省略参数类型int和string,编译器的语法糖,虽然没写,编译时还是有的,
                //根据委托推算的,因为NoReturnWithPara这个委托就是就是接收一个int和string
                NoReturnWithPara method3 = new NoReturnWithPara((id, name) => {
                    Console.WriteLine($"{id} {name} {age} 学习.Net高级班");
                });
                method3.Invoke(456, "张小姐");
    
                //如果方法体只有一行,可以去掉大括号和分号
                NoReturnWithPara method4 = new NoReturnWithPara((id, name) => 
                    Console.WriteLine($"{id} {name} {age} 学习.Net高级班")
                );
                method4.Invoke(789, "王小姐");
    
                //new NoReturnWithPara委托可以省掉,也是语法糖,编译器自动加上
                NoReturnWithPara method5 = (id, name) =>
                Console.WriteLine($"{id} {name} {age} 学习.Net高级班");
                method5.Invoke(101, "杨小姐");
            }
        }
    }

    2、省略参数类型int和string,编译器的语法糖,虽然没写,编译时还是有的,根据委托推算的,因为NoReturnWithPara这个委托就是就是接收一个int和string

    NoReturnWithPara method3 = new NoReturnWithPara((id, name) => {
        Console.WriteLine($"{id} {name} {age} 学习.Net高级班");
    });
    method3.Invoke(456, "张小姐");

    3、如果方法体只有一行,可以去掉大括号和分号

    //如果方法体只有一行,可以去掉大括号和分号
    NoReturnWithPara method4 = new NoReturnWithPara((id, name) => 
        Console.WriteLine($"{id} {name} {age} 学习.Net高级班")
    );
    method4.Invoke(789, "王小姐");

    4、new NoReturnWithPara委托也可以省掉,也是语法糖,编译器自动加上

    //new NoReturnWithPara委托可以省掉,也是语法糖,编译器自动加上
    NoReturnWithPara method5 = (id, name) =>
    Console.WriteLine($"{id} {name} {age} 学习.Net高级班");
    method5.Invoke(101, "杨小姐");
    • Lamda表达式是什么? 

    1、lamda不是一个委托,因为编译器语法糖省略了new NoReturnWithPara,所以只是看起来像是1个委托,但是实际上从上面可以看出lamda只是实例化委托的一个参数,lamda就是个匿名方法。

    2、从IL层分析,lamda是匿名方法,但是编译的时候会分配一个名字,还会产生一个私有sealed类,这里增加一个方法,这个方法就是跟lambda表达式一一对应的。

    • Lamda在多播委托中的特点--无法移除

    lamda表达式在多播委托为什么加1次,减1次,为什么减不掉呢?多播委托里面的lamda无法移除,虽说两个lamda的方法内容一样,lamda是匿名方法,但是编译器编译后会自动给分配方法名字,其实是2个不同的方法,所以无法移除,而Study是同1个方法,所以可以移除。

    namespace LamdaHistory
    {
        public class MulticastDelegate
        {
            public delegate void NoReturnWithPara(int x, string y);//声明委托
    
            public  void Show()
            {
                NoReturnWithPara method = new NoReturnWithPara(this.Study);
                method += this.Study;
                method += (id, name) => { Console.WriteLine($"{id} {name} 学习.Net Core"); };
    
                method -= this.Study;
                method -= (id, name) => { Console.WriteLine($"{id} {name} 学习.Net Core"); };
    
                method.Invoke(123, "张三");
            }
    
            private  void Study(int id, string name)
            {
                Console.WriteLine($"{id} {name} 学习.Net Framework");
            }
        }
    }

     

  • 相关阅读:
    在js中如何将字符串类型的日期("2020-11-30T02:21:42.000+0000")进行格式化
    微信小程序:报错fail webview count limit exceed
    微信小程序:picker组件实现下拉框效果
    微信小程序:post请求参数放在请求体中还是拼接到URL中需要看后台是如何接收的
    【华为云技术分享】如何用交互式特征工程工具进行数据分析处理
    【云小课】基础服务第25课 容灾演练:平时多练兵,急时保可用!
    【华为云分享】软件工程的迷途与沉思
    WebSocket 从入门到写出开源库
    教你轻松截获 Selenium 中的 Ajax 数据
    【华为云技术分享】Scrum Master如何引导团队中的刺头
  • 原文地址:https://www.cnblogs.com/menglin2010/p/12636490.html
Copyright © 2011-2022 走看看