• C# Lambda表达式学习笔记


        本笔记摘抄自:https://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html,记录一下学习过程以备后续查用。

        一、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
            }
    View Code

        总是使用 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
            }
        }
    View Code

        运行结果如下:

        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
            }
        }
    View Code

        运行结果如下:

        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
            }
        }
    View Code

        运行结果如下:

        四、揭开 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
            }
        }
    View Code

        运行结果如下:

        例子二:通过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
            }
        }
    View Code

        运行结果如下:

       例子三:定义一个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
            }
        }
    View Code

       运行结果如下:

        例子四:在计算商品的价格时,当商品重量超过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
            }
        }
    View Code

        运行结果如下:

        例子五:使用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
            }
        }
    View Code

        运行结果如下:

        例子六:此处使用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
            }
        }
    View Code

        运行结果如下:

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

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

  • 相关阅读:
    springboot配置视图控制器
    springboot测试的方法
    cookie之sameSite
    docker 安装Elasticsearch +kibana
    find + xargs 删除文件名中含有空格的文件
    git,composer 代理
    Composer更新依赖报错Fatal error解决方案
    compose 设置代理 SET HTTP_PROXY="http://192.168.1.103:8080"
    php使用composer常用问题及解决办法集:zlib_decode():data error......
    ERROR: .FileNotFoundError: [Errno 2] No such file or directory: '.\docker-compose.yml:docker-compose.apache.yml'
  • 原文地址:https://www.cnblogs.com/atomy/p/12080368.html
Copyright © 2020-2023  润新知