C# Lambda表達式學習筆記

    本筆記摘抄自:https://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html,記錄一下學習過程以備後續查用。html

    1、Lambda 的意義express

    在Framework 2.0 之前,聲明委託的惟一方法是經過方法命名,從Framework 2.0 起,系統開始支持匿名方法。經過匿名方法,能夠直接把一段代碼綁定ide

給事件,所以減小了實例化委託所需的編碼系統開銷。而在 Framework 3.0 開始,Lambda表達式開始逐漸取代了匿名方法,做爲編寫內聯代碼的首選方式。post

    整體來講,Lambda 表達式的做用是爲了使用更簡單的方式來編寫匿名方法,完全簡化委託的使用方式。學習

    2、回顧匿名方法的使用ui

    匿名方法的使用在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表達式開始出現。atom

    3、簡單介紹泛型委託spa

    在介紹Lambda表達式前,先介紹一下經常使用的幾個泛型委託。3d

    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

    運行結果以下:

    4、揭開 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的使用。

相關文章
相關標籤/搜索