欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# Lambda表达式学习笔记

程序员文章站 2022-06-20 08:46:09
本笔记摘抄自:https://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html,记录一下学习过程以备后续查用。 一、Lambda 的意义 在Framework 2.0 以前,声明委托的唯一方法是通过方法命名,从Framework 2.0 ......

    本笔记摘抄自:,记录一下学习过程以备后续查用。

    一、lambda 的意义

    在framework 2.0 以前,声明委托的唯一方法是通过方法命名,从framework 2.0 起,系统开始支持匿名方法。通过匿名方法,可以直接把一段代码绑定

给事件,因此减少了实例化委托所需的编码系统开销。而在 framework 3.0 开始,lambda表达式开始逐渐取代了匿名方法,作为编写内联代码的首选方式。

    总体来说,lambda 表达式的作用是为了使用更简单的方式来编写匿名方法,彻底简化委托的使用方式。

    二、回顾匿名方法的使用

    匿名方法的使用在c#委托与事件学习笔记中有简单介绍过,在此回顾一下:

        static void main(string[] args)
        {
            #region 事件的使用及方法绑定
            personmanager personmanager = new personmanager();
            //绑定事件处理方法方式一
            personmanager.myevent += new mydelegate(getname);
            //绑定事件处理方法方式二
            personmanager.myevent += getname;
            //绑定事件处理方法方式三(匿名方法)
            personmanager.myevent += delegate (string name) { console.writeline("my name is " + name); };
            personmanager.execute("atomy");
            console.read();
            #endregion
        }

    总是使用 delegate(){......} 的方式建立匿名方法,令人不禁感觉郁闷。于是从framework 3.0起,lambda表达式开始出现。

    三、简单介绍泛型委托

    在介绍lambda表达式前,先介绍一下常用的几个泛型委托。

    3.1 泛型委托 predicate<t>

    早在framework 2.0的时候,微软就为list<t>类添加了find、findall、foreach等方法用作数据的查找。

    public t find ( predicate<t> match)

    public list<t> findall(predicate<t>  match)

    在这些方法中存在一个predicate <t> 表达式,它是一个返回bool的泛型委托,能接受一个任意类型的对象作为参数。

    public delegate bool predicate<t>(t obj)

    在下面例子中,predicate委托绑定了参数为person类的方法match作为查询条件,然后使用findall方法查找到合适条件的list<person>集合。

    class program
    {
        #region 泛型委托 predicate<t>
        /// <summary>
        /// person类
        /// </summary>
        class person
        {
            public int id { get; set; }
            public string name { get; set; }
            public int age { get; set; }

            public person(int id, string name, int age)
            {
                id = id;
                name = name;
                age = age;
            }
        }

        /// <summary>
        /// 数据源
        /// </summary>
        /// <returns></returns>
        static list<person> getlist()
        {
            var personlist = new list<person>();
            var person = new person(1, "hello", 29);
            personlist.add(person);
            person = new person(1, "world", 31);
            personlist.add(person);
            return personlist;
        }

        /// <summary>
        /// 查询条件
        /// </summary>
        /// <param name="person"></param>
        /// <returns></returns>
        static bool match(person person)
        {
            return person.age <= 30;
        }
        #endregion

        static void main(string[] args)
        {
            #region 泛型委托 predicate<t>
            list<person> list = getlist();
            //绑定查询条件
            predicate<person> predicate = new predicate<person>(match);
            list<person> result = list.findall(predicate);
            console.writeline($"person count is : {result.count}");
            console.read();
            #endregion
        }
    }

    运行结果如下:

C# Lambda表达式学习笔记

    3.2 泛型委托 action

    action<t> 的使用方式与 predicate<t> 相似,不同之处在于 predicate<t> 返回值为 bool ,  action<t> 的返回值为 void。

    action 支持0~16个参数,可以按需求任意使用。

    public delegate void action()

    public delegate void action<t1> (t1 obj1)

    public delegate void action<t1,t2> (t1 obj1, t2 obj2)

    public delegate void action<t1,t2,t3> (t1 obj1, t2 obj2,t3 obj3)

    ............

    public delegate void action<t1,t2,t3,......,t16> (t1 obj1, t2 obj2,t3 obj3,......,t16 obj16)

    下面代码演示泛型委托action:

    class program
    {
        #region 泛型委托 action
        static void showmessage(string message)
        {
            console.writeline(message);
        }
        #endregion

        static void main(string[] args)
        {
            #region 泛型委托 action
            action<string> action = showmessage;
            action("hello world");
            console.readkey();
            #endregion
        }
    }

    运行结果如下:

C# Lambda表达式学习笔记

    3.3 泛型委托 func

    委托func与action相似,同样支持0~16个参数,不同之处在于func必须具有返回值。

    public delegate tresult func<tresult>()

    public delegate tresult func<t1,tresult>(t1 obj1)

    public delegate tresult func<t1,t2,tresult>(t1 obj1,t2 obj2)

    public delegate tresult func<t1,t2,t3,tresult>(t1 obj1,t2 obj2,t3 obj3)

    ............

    public delegate tresult func<t1,t2,t3,......,t16,tresult>(t1 obj1,t2 obj2,t3 obj3,......,t16 obj16)

    下面代码演示泛型委托func:

    class program
    {
        #region 泛型委托 func
        static double account(double a, bool condition)
        {
            if (condition)
                return a * 1.5;
            else
                return a * 2;
        }
        #endregion

        static void main(string[] args)
        {
            #region 泛型委托 func
            func<double, bool, double> func = account;
            double result = func(1000, true);
            console.writeline($"result is : {result}");
            console.read();
            #endregion
        }
    }

    运行结果如下:

C# Lambda表达式学习笔记

    四、揭开 lambda 神秘的面纱

    lambda的表达式的编写格式如下:x=> x * 1.5

    当中 “ => ”是lambda表达式的操作符,在左边用作定义一个参数列表,右边可以操作这些参数。

    例子一:先把int x设置1000,通过action把表达式定义为x=x+500,最后通过invoke激发委托。

    class program
    {
        static void main(string[] args)
        {
            #region lambda例子一
            int x = 1000;
            action action = () => x = x + 500;
            action.invoke();

            console.writeline($"result is : {x}");
            console.read();
            #endregion
        }
    }

    运行结果如下:

C# Lambda表达式学习笔记

    例子二:通过action<int>把表达式定义x=x+500,到最后输入参数1000,得到的结果与例子一相同。

    注意,此处lambda表达式定义的操作使用{ }括弧包括在一起,里面可以包含一系列的操作。

    class program
    {
        static void main(string[] args)
        {
            #region lambda例子二
            action<int> action = (x) =>
            {
                x = x + 500;
                console.writeline($"result is : {x}");
            };
            action.invoke(1000);
            console.read();
            #endregion
        }
    }

    运行结果如下:

C# Lambda表达式学习笔记

   例子三:定义一个predicate<int>,当输入值大约等于1000则返回true,否则返回false。与3.1的例子相比,predicate<t>的绑定不需要显式建立一个方法,

而是直接在lambda表达式里完成,简洁方便了不少。

    class program
    {
        static void main(string[] args)
        {
            #region lambda例子三
            predicate<int> predicate = (x) =>
            {
                if (x >= 1000)
                    return true;
                else
                    return false;
            };
            bool result = predicate.invoke(500);
            console.writeline($"result={result}");
            console.read();
            #endregion
        }
    }

   运行结果如下:

C# Lambda表达式学习笔记

    例子四:在计算商品的价格时,当商品重量超过30kg则打9折,其他按原价处理。此时可以使用func<double,int,double>,参数1为商品原价,参数2为商品

重量,最后返回值为 double 类型。

    class program
    {
        static void main(string[] args)
        {
            #region lambda例子四
            func<double, int, double> func = (price, weight) =>
            {
                if (weight >= 30)
                    return price * 0.9;
                else
                    return price;
            };
            double totalprice = func(200.0, 40);
            console.writeline($"totalprice={totalprice}");
            console.read();
            #endregion
        }
    }

    运行结果如下:

C# Lambda表达式学习笔记

    例子五:使用lambda为button定义click事件的处理方法,使用lambda比使用匿名方法更加简单。

    public partial class main : form
    {
        public main()
        {
            initializecomponent();
        }

        private void main_load(object sender, eventargs e)
        {
            #region lambda例子五
            btnevent.click += (obj,arg)=>
            {
                messagebox.show("hello world");
            };
            #endregion
        }
    }

    运行结果如下:

C# Lambda表达式学习笔记

    例子六:此处使用3.1的例子,在list<person>的findall方法中直接使用lambda表达式。相比之下,使用lambda表达式,不需要定义predicate<t>对象,也

不需要显式设定绑定方法,简化了不工序。

    class program
    {
        #region 泛型委托 predicate<t>
        /// <summary>
        /// person类
        /// </summary>
        class person
        {
            public int id { get; set; }
            public string name { get; set; }
            public int age { get; set; }

            public person(int id, string name, int age)
            {
                id = id;
                name = name;
                age = age;
            }
        }

        /// <summary>
        /// 数据源
        /// </summary>
        /// <returns></returns>
        static list<person> getlist()
        {
            var personlist = new list<person>();
            var person = new person(1, "hello", 29);
            personlist.add(person);
            person = new person(1, "world", 31);
            personlist.add(person);
            return personlist;
        }

        /// <summary>
        /// 查询条件
        /// </summary>
        /// <param name="person"></param>
        /// <returns></returns>
        static bool match(person person)
        {
            return person.age <= 30;
        }
        #endregion

        static void main(string[] args)
        {
            #region lambda例子六
            list<person> personlist = getlist();
            //查找年龄少于30年的人
            list<person> result = personlist.findall((person) => person.age <= 30);
            console.writeline("person count is : " + result.count);
            console.read();
            #endregion
        }
    }

    运行结果如下:

C# Lambda表达式学习笔记

    当在使用linq技术的时候,到处都会弥漫着lambda的身影,此时更能体现lambda的长处。但linq涉及到分部类、分部方法、ienumerable<t>、迭代器等

多方面的知识,这些已经超出本章的介绍范围。通过这一节的介绍,希望能够帮助大家更深入地了解lambda的使用。