C# Lambda表達式學習筆記

来源:https://www.cnblogs.com/atomy/archive/2019/12/23/12080368.html
-Advertisement-
Play Games

本筆記摘抄自:https://www.cnblogs.com/leslies2/archive/2012/03/22/2389318.html,記錄一下學習過程以備後續查用。 一、Lambda 的意義 在Framework 2.0 以前,聲明委托的唯一方法是通過方法命名,從Framework 2.0 ...


    本筆記摘抄自: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的使用。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • $GLOBALS——引用全局作用域中可用的全部變數。 $GLOBALS一個包含了全部變數的全局組合數組。變數的名字就是數組的鍵。(即所有出現過的全局變數,都可通過$GLOBALS獲取到) 在PHP中,定義在函數體外的全局變數,函數內部是不能直接獲取的,所以需要global聲明或者$GLOBALS[] ...
  • 1)set中每個元素的值都唯一,而且系統能根據元素的值自動進行排序。set中元素的值不能直接被改變 set具備的兩個特點: 1. set中的元素都是排序好的 2. set中的元素都是唯一的,沒有重覆的 2)聲明:例:set<int> s; 3)set的常用的方法 (s.~) begin(); // ...
  • 由於當前C++項目需要使用ajax庫去post調用ashx介面,介面地址如下所示: 需要傳遞的參數如下: 然後發現qml比較好調用ajax.js庫,所以本章通過C++界面去獲取qml方法來實現調用ashx介面(以一個C++界面demo程式為例) 1.抓post數據 通過網頁獲取到的post數據如下所 ...
  • 第八章 多態 多態的條件: 1. 要有繼承 2.父類對象引用子類對象 3. 要有方法的重寫 多態的作用:消除類型之間的耦合關係。 將一個方法調用與一個方法主體關聯起來稱作綁定。若在程式執行前進行綁定,叫做前期綁定;在運行時根據對象的類型進行綁定,叫做後期綁定,也叫動態綁定、運行時綁定。 Java中除 ...
  • 【ASP.NET Core學習】 介紹在gRPC使用,將從從(What)什麼是RPC,(When)什麼時候需要使用RPC,(How)如何使用gRPC。 RPC是Remote Procedure Call簡稱,翻譯過來是遠程過程調用。它是一個進程間的通訊技術,基於Client-Server模式,讓程... ...
  • 在編寫Dockerfile構建docker鏡像時,常遇到以下問題: 為瞭解決上述問題,從17.05版本開始Docker在構建鏡像時增加了新特性:多階段構建(multi-stage builds),將構建過程分為多個階段,每個階段都可以指定一個基礎鏡像,這樣在一個Dockerfile就能將多個鏡像的特 ...
  • 在開發WPF應用時出現:”調用線程無法訪問此對象,因為另一個線程擁有該對象。“ 是因為UI線程是WPF應用的主線程,若嘗試子線程更新UI線程應使用Dispatcher.BeginInvoke()或者Invoke()方法。 Dispatcher.BeginInvoke() //非同步執行,不等待委托結束 ...
  • 上一篇文章https://www.cnblogs.com/mbpframework/p/12073102.html,介紹了一下Mbp的框架.其實這個框架寫出來主要是為了學習,當然也可以經過優化運用到實際的項目中.今天我們來說說怎麼使用這個框架. 首先我們用分層的方式來規划下我們的項目代碼結構. Me ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...