日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

[深入学习C#]匿名函数、委托和Lambda表达式

發布時間:2025/3/11 C# 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [深入学习C#]匿名函数、委托和Lambda表达式 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自詩人江湖老,原文地址

  匿名函數(Anonymous Function)是表示“內聯”方法定義的表達式。匿名函數本身及其內部沒有值或者類型,但是可以轉換為兼容的委托或者表達式樹類型(了解詳情)。匿名函數轉換的計算取決于轉換的目標類型:如果是委托類型,則轉換計算為引用匿名函數所定義的方法的委托;如果是表達式樹類型,則轉換將計算以對象結構形式表示方法結構的表達式樹。
  匿名函數有兩種語法風格:Lambda表達式(lambda-expression)匿名方法表達式(anonymous-method-expression)。在幾乎所有的情況下,Lambda表達式都比匿名方法表達式更為簡介具有表現力。但現在C#語言中仍保留了后者,為了向后兼容。
  Lambda表達式:
    async可選 (匿名的函數簽名)=> (匿名的函數體)
  匿名方法表達式:
    async可選 delegate (顯式的匿名函數簽名) 可選{代碼塊}

  其中匿名的函數簽名可以包括兩種,一種是隱式的匿名函數簽名另一種是顯式的匿名函數簽名
    隱式的函數簽名:(p)、(p1,p1)
    顯式的函數簽名:(int p)、(int p1,int p2)、(ref int p1,out int p2)
  匿名的函數體可以是表達式或者代碼塊。

  從上面我們可以看出,Lambda表達式的參數形式可以顯式或者隱式類型化。在顯式類型化參數列表中,每個參數的類型是顯式聲明的,在隱式類型化參數列表中,參數的類型是從匿名函數出現的上下文中推斷出來的。
  當Lambda表達式只有一個具有隱式類型化參數的時候,參數列表可以省略圓括號,也就是說:
  (參數) => 表達式
  可以簡寫為
  參數 => 表達式

一些匿名函數的示例
  x => x + 1 //隱式的類型化,函數體為表達式
  x => {return x + 1;} //隱式的類型化,函數體為代碼塊
  (int x) => x + 1 //顯式的類型化,函數體為表達式
  (int x) => {return x + 1;} //顯式的類型化,函數體為代碼塊
  (x , y) => x * y //多參數
  () => Console.WriteLine() //無參數
  async (t1 , t2) => await t1 + await t2 //異步
  delegate (int x) {return x + 1;} //匿名函數方法表達式
  delegate {return 1 + 1;} //參數列表省略
  
Lambda表達式和匿名方法表達式的區別:
  ● 當沒有參數的時候,匿名方法表達式允許完全省略參數列表,從而可以轉換為具有任意值參數列表的委托類型,Lambda表達式則不能省略參數列表的圓括號()。
  ● Lambda表達式允許省略和推斷類型參數,而匿名方法表達式要求顯式聲明參數類型。
  ● Lambda表達式主體可以為表達式或者代碼塊,而匿名方法表達式的主體必須為代碼塊。
  ● 只有Lambda表達式可以兼容到表達式樹類型。

委托

  一個委托是一個指向一個方法的引用,或者說,一個委托的實例就是一個指向某個方法的對象,這是一個簡單卻十分強大的概念。
  C#中的委托是用來處理在其他語言中(如C++、Pascal等)需要用函數指針來處理的情況。不過與C++不同的是:委托是完全面向對象的;C++指針僅僅指向成員函數,而委托同時封裝了對象的實例和方法;委托是完全類型安全的,只有當函數的簽名與委托的簽名匹配的時候,委托才可以指向該方法,當委托沒有合法的指向方法的時候不能被調用。

  一些關于委托的知識點:
  
  1.委托是類型安全的
  委托類型的返回類型必須為void或者輸出安全,委托類型的所有形參類型都必須是輸入安全的。
  
  2.委托類型是名稱等效,不是結構等效
  也就是說,對于兩個委托類型,即使它們具有相同的參數列表和返回類型,它們仍將被視為兩個不同的委托類型。
  例如:
  delegate int A(int x);
  delegate int B(int x);
  A和B是兩個不同的委托。
  
  但是,兩個結構一樣的委托,它們的實例可以指向同一個方法。
  
  3.委托的調用列表(多播委托)
  委托實例所封裝的方法集合稱為調用列表。
  當我們從某個方法創建一個委托實例的時候,該實例將封裝此方法,該實例中的調用列表包含一個“入口點”。當我們組合多個非空的委托實例的時候,它們的調用列表將連接在一起形成一個新的調用列表,新的調用列表中包含了多個“入口點”。
  委托的組合是使用二元運算符 + 和 += 來進行的,同樣可以使用 - 和 -= 來進行組合的移除。
  
  下面的示例演示多個委托的實例化及其相應的調用列表:

delegate void D(int x) class {public static void M1(int i){...}public static void M2(int i){...} } class Test {static void Main(){D cd1 = new D(c.M1); //M1D cd2 = new D(c.M2); //M2D cd3 = cd1 + cd2; //M1 + M2D cd4 = cd3 + cd1; //M1 + M2 + M1D cd5 = cd4 + cd3; //M1 + M2 + M1 + M2} }

  實例化cd1和cd2的時候,它們分別封裝一個方。實例化cd3的時候,它調用的列表有兩個方法M1和M2,而且順序與此相同。cd4的調用列表中依次包含M1、M2、M1。最后,cd5的調用列表中依次包含M2、M1、M1、M2。
  
  4.委托的調用
  當調用一個委托實例的時候,將按照調用列表的順序依次調用列表中的各個方法,當在調用期間發生異常,調用列表中排在后面的任何方法將不會被調用。

using System; delegate void D(int x); class C {public static void M1(int i){Console.WriteLine("C.M1:"+i);}public static void M2(int i){Console.WriteLine("C.M1:"+i);}  public void M3(int i){Console.WriteLine("C.M2:"+i);} }class Test {static void Main(){D cd1 = new D(c.M1); //M1cd1(-1); //調用cd1D cd2 = new D(c.M2); //M2cd2(-2); //調用M2D cd3 = cd1 + cd2; //M1 + M2cd3(10); //依次調用M1、M2cd3 += cd1;cd3(20); //依次調用M1、M2、M1C c = new C();D cd4 = new D(c.M3); cd3 += cd4;cd3(30); //依次調用M1、M2、M1、M3cd3 -= cd1 //移除最后一個M1cd3(40); //依次調用M1、M2、M3cd3 -= cd4; cd3(50); //依次調用M1、M2cd3 -= cd2cd3(60); //調用M1cd3 -= cd2 //這是cd3的調用列表中沒有cd2了,該移除不生效,不報錯cd3(70); //調用M1cd3 -= cd1 // cd3(70); //如果調用,將會報System.NullReferenceException異常} }

Lambda表達式

  自從C#3.0開始,就可以使用一種新語法把實現代碼賦予委托:Lambda表達式。只要有委托參數類型的地方,就可以使用Lambda表達式。使用匿名方法的地方可以使用Lambda表達式來代替,例如:

Func< string,string > = delagate(string para) {para += "Hello World!";return param; }可以寫成 Func< string,string > = para=> {para +="Hello World!";return para; }

  Lambda表達式運算符”=>”的左邊列出了需要的參數,右邊定義了賦予Lambda變量的方法的代碼實現。
  我們注意到,無論何時,只要我們需要引入匿名方法,我們都需要在前面加上delegate關鍵字,而且參數列表都需要類型化。Lambda表達式提供了一種更為簡潔和自然的語法,而且在C#更多高級的方面中都涉及廣泛。簡而言之,我們應該用Lambda表達式來替代匿名方法。
  例如:

public class Person {string Name;int Age; }List<Person> personList = new List<Person>();personList.Find(delegate(Person p){retrun p.Age==12;}); //可以寫成 personList.Find(p=>p.Age==12);

添加鏈接描述

總結

以上是生活随笔為你收集整理的[深入学习C#]匿名函数、委托和Lambda表达式的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。