• 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的使用。

  • 相关阅读:
    Infopath Notify 弹出提示信息
    window.showModalDialog 返回值
    【转】获得正文内容中的所有img标签的图片路径
    Json Datable Convert
    Sharepoint 列表 附件 小功能
    Surgey 权限更改
    SQL 触发器用于IP记录转换
    Caml语句 查询分配给当前用户及当前组
    jquery 1.3.2 auto referenced when new web application in VSTS2010(DEV10)
    TFS diff/merge configuration
  • 原文地址:https://www.cnblogs.com/atomy/p/12080368.html
Copyright © 2020-2023  润新知