zoukankan      html  css  js  c++  java
  • 匿名方法Lambda 表达式

    =============================版权申明===============================

      任何人都可以转载,但请注明转载地址和作者“天轰穿”,因为下面这是我正在写的 c# 这本书中的节选内容。

    整本书都是这个风格,朋友们有啥期待尽管提。

    ===========================版权申明结束,内容开始====================== 

    6.3.5 匿名方法

    小天:我觉得多少还是有点死板。有不有什么办法可以让委托更灵活,比如某个阶段我并不确定具体要调用的被委托方法名。或者根本不想专门为某个委托就写一个冷僻的方法。

    老田:可以使用匿名方法。在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法。C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方式。不过,本章讨论的这些内容也同样也适用于 Lambda 表达式(稍后讨论)。有一种情况下,匿名方法提供了 Lambda 表达式中所没有的功能。匿名方法使您能够省略参数列表,这意味着可以将匿名方法转换为带有各种签名的委托。这对于 Lambda 表达式来说是不可能的。

    要将代码块传递为委托参数,创建匿名方法则是唯一的方法。下面新建一个Windows窗体应用程序,在Form1的设计界面上拖一个button,然后在窗体空白处点右键,查看代码,在Form1的构造函数中编写代码,为button1click关联一个匿名方法作为执行体,具体Form1的构造函数代码如下:

            public Form1()

            {

                InitializeComponent();

                button1.Click += delegate(Object o, EventArgs e)

                {

                    //匿名事件中的代码

                    MessageBox.Show("按钮事件!");

                }; //注意大括号后面有一个分号作为结束

            }

    然后运行程序。会发现,点击按钮执行的事件就是我们上面写的这个;

    小天:匿名方法一定要跟上面示例中这两个参数吗?

    老田:当然不是,上面示例之所以要跟这两个参数是因为buttonclick委托规定了接受他委托的方法的要求是这样的。否则我们也可以像下面这样:

                //自定义一个委托类型(注意申明委托的位置,错了别怪我)

                delegate void Del(int x);

     

                //申明一个Del委托类型的实例,并为他关联一个匿名类型的匿名事件

                Del d = delegate(int k) { /* 方法体 */ };

    名方法的优点是减少了要编写的代码。不必定义仅由委托使用的方法。在为事件定义委托时,这是非常显然的。这有助于降低代码的复杂性,尤其是定义了好几个事件时,代码会显得比较简单。使用匿名方法时,代码执行得不太快。编译器仍定义了一个方法,该方法只有一个自动指定的名称,我们不需要知道这个名称。

    在使用匿名方法时,必须遵循两个规则。在匿名方法中不能使用跳转语句跳到该匿名方法的外部,反之亦然:匿名方法外部的跳转语句不能跳到该匿名方法的内部。

    在匿名方法内部不能访问不安全的代码。另外,也不能访问在匿名方法外部使用的refout参数。但可以使用在匿名方法外部定义的其他变量。

    如果需要用匿名方法多次编写同一个功能,就不要使用匿名方法。而编写一个指定的方法比较好,因为该方法只需编写一次,以后可通过名称引用它。

     

    6.3.6  Lambda表达式

    C# 3.0为匿名方法提供了一个新的语法:Lambda表达式。Lambda表达式可以用于委托类型。“Lambda表达式”是一个匿名函数,它可以包含表达式和语句,并且可用于创建委托或表达式目录树类型。

    所有 Lambda 表达式都使用 Lambda 运算符 =>,该运算符读为“goes to”。该 Lambda 运算符的左边是输入参数(如果有),右边包含表达式或语句块。Lambda 表达式 x => x * x 读作“x goes to x * x”。可以将此表达式分配给委托类型,如下所示:

        class Program

        {

            delegate int del(int i);

     

            static void Main(string[] args)

            {

                del myDelegate = x => x * x;

                int j = myDelegate(5); //j的值为调用委托所得到的值

                Console.WriteLine(j);   //值为25

                Console.ReadLine();

            }

        }

    现在基本上明白了Lambda表达式的写法,接下来我们结合匿名方法来做一个实例:

        class Program

        {

            delegate int del(int i);

     

            static void Main(string[] args)

            {

                del myDelegate = x => x * x;

                int j = myDelegate(5); //j的值为调用委托所得到的值

                Console.WriteLine(j);   //值为25

                //注意这里result实际上是del委托类的参数,所以一定是int类型

                del d1 = result =>    

                    {

                        result += 10;   //对传入的result参数做简单处理

                        return result; //返回结果

                    }; //注意大括号后面有一个分号作为结束

     

                Console.WriteLine(d1(2));   //直接调用委托,结果显示12

                Console.ReadLine();

            }

        }

    老田:给你布置个任务,自定义一个多个参数的委托类型,结合Lambda表达式和匿名方法来做个实例。

    小天:等等先问两个问题:

    1.                  为什么你上面第一个例题 del myDelegate = x => x * x;  这段代码中 => 符号后面的x * x 没有给大括号,但是第二个是给的大括号?

    2.                  多个参数在 => 符号前面怎么表示?

     

    老田:第一个问题:如同if语句一样,如果下面只有一行代码,则可以省略大括号;例如下面这样也是对的

                del myDelegate = x =>{ x * x};

     

    第二个问题:多个参数任然写在=> 符号前面,不过需要用括号括起来,同时多个参数之间用逗号分隔,例如

    Del d1 = (x, y, z) => z + y + z;

    小天:那就简单了。如下,我定义了一个名为XiaoTian的委托,两个参数,然后在匿名方法中对参数进行了简单的处理,最后返回这里我还做了点举一反三,如下:

        class Program

        {

            //三个参数的委托

            delegate string XiaoTian(string xr, int age, string sex);

     

            static void Main(string[] args)

            {

                //多个参数就必须使用括号,参数之间用逗号分隔

                XiaoTian xt = (xr, age, sex) =>

                    {

                        StringBuilder jg = new StringBuilder();

                        jg.Append("小天此人今年");

                        jg.Append(age);

                        jg.Append("岁,性别");

                        jg.Append(sex);

                        jg.Append(",长相");

                        jg.Append(xr);

                        return jg.ToString();   //直接返回结果

                    };

                //调用委托

                Console.WriteLine(xt("帅得一塌糊涂", 28, "男"));

                Console.ReadLine();

            }

        }

    运行后效果如图6-6

     

                                                     6-6

    老田:不错。上面我们讨论的都是预定义参数的情况下,那么假设传入的参数类型是自定义的类型,恰恰编译器推断不出来怎么办呢?那么接下来就要说到的是在为参数指定类型,如下:

        //自定义一个有两个属性的类

        class Thc

        {

            public Thc(string n, int a)

            {

                Name = n;

                Age = a;

            }

            public string Name { get; set; }

            public int Age { get; set; }

    }

    //控制台应用程序的起始类

       class Program

        {

            //使用自定义类型的参数

            delegate string More(Thc t);

            static void Main(string[] args)

            {

                //对参数申明类型

                More m =(Thc t )=>

                    {

                        return "姓名为" + t.Name + ",年龄" + t.Age;

                    };

                //调用委托,注意所给的参数是新实例一个对象

                Console.WriteLine(m(new Thc("天轰穿", 30)));

                Console.ReadLine();

            }

        }

           小天:上面说了这么多都是有参数的,如果遇上没有参数的咋办?

           老田:没有参数更省事,直接给个空的括号就行,如下:

        class Program

        {

            //无参数

            delegate void Wucanshu();

     

            static void Main(string[] args)

            {

                //对于无参数的情况就直接给一个空的括号就行了

                Wucanshu wcs = () =>

                {

                    Console.WriteLine( "我就是无参数,你把我咋样嘛!");

                };

                //调用委托

                wcs();

                Console.ReadLine();

            }

        }

  • 相关阅读:
    1094. Car Pooling
    121. Best Time to Buy and Sell Stock
    58. Length of Last Word
    510. Inorder Successor in BST II
    198. House Robber
    57. Insert Interval
    15. 3Sum java solutions
    79. Word Search java solutions
    80. Remove Duplicates from Sorted Array II java solutions
    34. Search for a Range java solutions
  • 原文地址:https://www.cnblogs.com/yangleiWPF/p/1716438.html
Copyright © 2011-2022 走看看