分享

C#中的Lambda表达式简介

 老马的程序人生 2020-08-17

一般我们学习C#说到匿名函数的时候,都会谈到Lambda表达式。其实Lambda表达式就是匿名函数更为简洁的一种写法,这个概念是来自函数式编程,很多语言都加入了这个功能。

通俗点讲,你需要写一个函数,但是懒得给它起名字,而且懒得写那么多封装和类,并且可能就这个地方调用,其他地方几乎不调用这段代码,那么我就可以用这个来搞定。

注:在C#2.0中,通过匿名方法,使委托的实现得到了极大的简化。但是匿名方法仍然有些臃肿,而且当代码中充满了匿名方法的时候,可读性就会受到影响。C#3.0中出现的Lambda表达式在不牺牲可读性的前提下,进一步简化了委托。

Lambda运算符:

=>运算符将表达式分为两部分,左边指定输入参数,右边是Lambda的主体,表达式或语句块。

Lambda表达式:

一个参数:param =>expr

多个参数:(param-list)=> expr

Lambda的应用:

using System.Collections.Generic;

using System.Linq;

using System;

namespace LambdaSample01

{

    internal class Person

    {

        public string Name { get; set; }

        public int Age { get; set; }

        public override stringToString()

        {

            returnstring.Format("Name:{0},Age{1}",Name, Age);

        }

    }

    class Program

    {

        privatestatic List<Person> GetPersonList()

        {

            List<Person> lst = newList<Person>();

            for(int i = 0; i < 7; i++)

            {

                Personp;

                if(i%2 == 0)

                    p = new Person() {Name = i + "儿子", Age = 8 - i};

                else

                    p = new Person() {Name = i + "女儿", Age = 8 - i};

                lst.Add(p);

            }

            returnlst;

        }

        static void Main(string[]args)

        {

            List<Person> persons = GetPersonList();

            Action<Person> printer = person => Console.WriteLine(person.ToString());

            persons.ForEach(printer);

            Console.WriteLine("-------------------");

            //所有Age>6的Person的集合

            List<Person> person1 = persons.Where(delegate(Person p){ return p.Age > 6; }).ToList();

            person1.ForEach(printer);

            Console.WriteLine("-------------------");

            List<Person> person2 = persons.Where(p => p.Age> 6).ToList();

            person2.ForEach(printer);

            Console.WriteLine("-------------------");

            //所有Name包含儿子的Person的集合

            List<Person> person3 = persons.Where(p =>p.Name.Contains("儿子")).ToList();

            person3.ForEach(printer);

            Console.WriteLine("-------------------");

            //Age = 4的单个People

            Personper = persons.SingleOrDefault(p => p.Age == 4);

            Console.WriteLine(per);

            Console.WriteLine("-------------------");

            //使用Lambda表达式对List<T>进行排序

            persons.Sort((per1, per2) =>per1.Age.CompareTo(per2.Age));

            persons.ForEach(printer);

        }

    }

}

见代码:LambdaSample01.cs

看了上面的例子,相信你能看出它确实是个甜枣,Lambda表达式是由.Net2.0演化而来,也是LINQ的基础,熟练地掌握Lambda表达式能够快速上手LINQ应用开发(LINQ的基本功能就是创建操作管道,以及这些操作需要的任何状态。这些操作表示了各种关于数据的逻辑,例如数据筛选,数据排序等等。通常这些操作都是用委托来表示。Lambda表达式是对LINQ数据操作的一种符合语言习惯的表示方式。),下面我们来看看(p => p.Age > 6)这样的表达式,到底是怎么回事。

注:

List<Person> person1= persons.Where(delegate(Person p) { returnp.Age > 6; }).ToList();

List<Person> person2= persons.Where(p => p.Age > 6).ToList();

从这里可以看出Lambda表达式在编写的格式上和匿名方法非常相似。其实,当编译器开始编译并运行时,Lambda表达式最终也表现为匿名方法。使用匿名方法并不是创建了没有名称的方法,实际上编译器会创建一个方法,这个方法对开发人员来说是不可见的,该方法会将Person类的对象返回并填充到集合中。相同地,使用Lambda表达式,当编译器编译时,Lambda表达式同样会被编译成一个匿名方法进行响应的操作,但是与匿名方法相比,Lambda表达式更容易阅读。

首先,我们要看下委托:

using System;

namespace LambdaSample02

{

    delegate int Algorithm1(int a);

    delegate void Algorithm2(int a, int b);  

    class Program

    {

        static void Main(string[]args)

        {

            //普通委托

            Algorithm1zw1 = JieZhang;

            //利用委托来写匿名函数

            Algorithm2zw2 = delegate(inta, int b)

                {

                    Console.WriteLine("{0}*{1}={2}", a, b, a*b);

                };

            Console.WriteLine(zw1(10));

            zw2(10, 20);

        }

        privatestatic intJieZhang(int a)

        {

            returna + 10;

        }

    }

}

见代码:LambdaSample02.cs

再看表达式:

using System;

namespace LambdaSample03

{

    delegate int Algorithm1(int a);

    delegate void Algorithm2(int a, int b);  

    class Program

    {

        static void Main(string[]args)

        {

            //利用Lambda表达式来写一模一样的功能

            Algorithm1zw1 = p => p + 10;

            Algorithm2zw2 = (p, q) => Console.WriteLine("{0}*{1}={2}", p, q, p*q);

            Console.WriteLine(zw1(10));

            zw2(10, 20);

        }

    }

}

见代码:LambdaSample03.cs

委托跟表达式的两段代码,我们可以看出,可以将Lambda表达式分配给委托,表达式(p => p+10;)中的p就是代表委托方法中的参数,而表达式符号右边的p+10,就是委托方法中的返回结果。

下面再上两个稍微复杂点的理解一下:

1.Lambda主体运算复杂

using System;

namespace LambdaSample05

{

    class Program

    {

        privatedelegate int GuangChaoShi(inta, int b);

        static void Main(string[]args)

        {

            GuangChaoShizw1 = (p, q) =>

                {

                    constint min = 10;

                    if(p < min)

                        return 100;

                    else

                        return q - p - 10;

                };

            Console.WriteLine(zw1(10,100));

        }

    }

}

见代码:LambdaSample05.cs

注意:匿名函数的参数和返回值必须要和委托一样。

2.综合例子

using System;

using System.Collections.Generic;

namespace LambdaSample04

{

    class Program

    {

        static void Main(string[]args)

        {

            Console.WriteLine("传统的委托代码示例:");

            FindListDelegate();

            Console.WriteLine("使用匿名方法代码示例:");

            FindAnonymousMethod();

            Console.WriteLine("使用Lambda表达式代码示例:");

            FindLambdaExpression();

        }

        privatestatic voidFindListDelegate()

        {

            List<string> list = newList<string>();

            list.AddRange(new string[] {"ASP.NET课程", "J2EE课程","PHP课程","数据结构与算法"});

            Predicate<string> findPredicate = IsBookCategory;

            List<string> bookCategory =list.FindAll(findPredicate);

            foreach(string str inbookCategory)

            {

                Console.WriteLine("{0}\t", str);

            }

        }

        privatestatic boolIsBookCategory(string str)

        {

            returnstr.EndsWith("课程") ? true : false;

        }

        privatestatic voidFindAnonymousMethod()

        {

            List<string> list = newList<string>();

            list.AddRange(new string[] { "ASP.NET课程", "J2EE课程", "PHP课程", "数据结构与算法" });

            List<string> bookCategory = list.FindAll(

                delegate(string str)

                    {

                        return str.EndsWith("课程") ? true : false;

                    });

            foreach(string str inbookCategory)

            {

                Console.WriteLine("{0}\t", str);

            }

        }

        privatestatic voidFindLambdaExpression()

        {

            List<string> list = newList<string>();

            list.AddRange(new string[] { "ASP.NET课程", "J2EE课程", "PHP课程", "数据结构与算法" });

            List<string> bookCategory = list.FindAll(

                p => p.EndsWith("课程") ? true: false);

            foreach(string str inbookCategory)

            {

                Console.WriteLine("{0}\t", str);

            }

        }

    }

}

见代码:LambdaSample04.cs

Func<TResult>委托:

TResult是参数类型,这是一个泛型类型的委托。

先上例子:

using System;

namespace LambdaSample06

{

    class Program

    {

        static void Main(string[]args)

        {

            //使用C# 2.0中的匿名方法获取字符串长度

            Func<string, int>strLength = delegate(stringstr)

                {

                    returnstr.Length;

                };

            Console.WriteLine(strLength("Hello World"));

            //使用Lambda表达式

            //(显示类型参数列表) => {语句},Lambda表达式最冗长版本

            strLength = (string str) =>

                {

                    returnstr.Length;

                };

            Console.WriteLine(strLength("Hello World"));

            //单一表达式作为主体

            //(显示类型参数列表) => 表达式

            strLength = (string str) => str.Length;

            Console.WriteLine(strLength("Hello World"));

            //隐式类型的参数列表

            //(隐式类型参数列表) => 表达式

            strLength = (str) => str.Length;

            Console.WriteLine(strLength("Hello World"));

            //单一参数的快捷语法

            //参数名 => 表达式

            strLength = str => str.Length;

            Console.WriteLine(strLength("Hello World"));

            Func<int, string> zw1 =p => p + 10 + "--返回类型为string.";

            Console.WriteLine(zw1(10));

        }

    }

}

见代码:LambdaSample06.cs

说明:我们可以看到,这里的pint类型参数,然而Lambda主体返回的是string类型的。

再上一个例子:

using System;

namespace LambdaSample07

{

    class Program

    {

        static void Main(string[]args)

        {

            Func<int, int, bool> zw1 = (p, j) =>

                {

                    if(p + j == 10)

                        return true;

                    else

                        return false;

                };

            Console.WriteLine(zw1(5,5));

        }

    }

}

见代码:LambdaSample07.cs

说明:从这个例子,我们看到,pint类型,jint类型,返回值bool类型。

Func<T>的用法:多个参数,前面的为委托方法的参数,最后一个参数,为委托方法的返回类型。


通过微信学习的知识只能是碎片化的知识,作为新时代的我们希望能够构建自己的知识结构,使我们的知识体系化,系统化,以后在遇到碎片化的知识,我们做的只是融合到自己的知识结构中,故我们将推出“与LSGO一起学”系列课程,帮助大家来构建知识框架,初步规划有:

  1. “与LSGO一起学C++”;

  2. “与LSGO一起学C#”;

  3. LSGO一起学Matlab”;

  4. “与LSGO一起学数据结构”;

  5. “与LSGO一起学设计模式”;

  6. “与LSGO一起学可视化建模语言(UML)”;

  7. “与LSGO一起学线性代数”;

  8. “与LSGO一起学高等数学”

  9. “与LSGO一起学概率论与数理统计”;

  10. “与LSGO一起学抽象代数;

  11. “与LSGO一起学点集拓扑”

  12. “与LSGO一起学数字图像处理”;

  13. “与LSGO一起学智能计算”;

如果对这些内容感兴趣,可以一起来学习讨论。

我们的官网: www.lsgogroup.com

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多