標籤:
上一篇部落客要是對委託和事件做了一小結,這篇是在上一篇部落格的基礎上對匿名函數和Lambda運算式小結。還是接著上一篇說起,在上一篇中也說了委託是一種資料結構,主要是解決讓函數作為參數的問題。在使用委託時首先要聲明代理,然後執行個體化,並將委派物件和已定義好的函數關聯上,最後調用。這裡與已定義好的函數關聯的事情,如果函數是經常使用的也還好,如果不是經常使用的可能只調用一次,那這豈不是老費勁了。就是能不能在使用的時候定義下呢?於是乎有了匿名方法。
一、匿名方法的使用。
匿名方法的使用步驟和委託的使用步驟相同,只是執行個體化的格式不同。匿名方法的格式:
委託名 執行個體變數 =delegate(形參列表)
{
};
1.形參列表:參數列表應該和委託聲明的匹配。若無可用()表示
2.傳回值:傳回值也是需要和委託類型的傳回值匹配。
二、demo
和委託事件的例子一樣,還是定義了一個Person類,並聲明了委託EatFoodDelegate。
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Delegate{ //定義了一個從System.Delegate類派生的類 //也可以理解為一種資料類型 這種資料類型指向傳回值為void 參數為Person對象的函數 //我們也可以把Person類理解為一種資料類型 只是它包含的是Name和Age public delegate void EatFoodDelegate(Person p); public class Person { public string Name { get; set; } public int Age { get; set; } public Person(string name, int age) { Name = name; Age = age; } //既然委託是一資料類型和String一樣,所以可以像聲明String對象一樣聲明代理變數 public EatFoodDelegate eatFoodDelegate; ////之前是直接聲明委託,現在是聲明一個事件 //public event EatFoodDelegate EatFoodEventHandler; public void eating() { if (eatFoodDelegate != null) { eatFoodDelegate(this); } } }}
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Delegate{ class Program { static void Main(string[] args) { Person chinesePerson = new Person("小明",25); //通過建構函式執行個體化對象 chinesePerson.eatFoodDelegate += new EatFoodDelegate(chineseEat); chinesePerson.eating(); Console.WriteLine("--------------------------------------"); EatFoodDelegate EnglishEatPisaDelegate = delegate (Person p) { Console.WriteLine("I‘m {0},I am {1} , I eat PiSa", p.Name, p.Age); }; Person englishPerson = new Person("Ivan",25); englishPerson.eatFoodDelegate = delegate (Person p) { Console.WriteLine("I‘m {0},I am {1} , I eat MianBao", p.Name, p.Age); }; englishPerson.eatFoodDelegate += EnglishEatPisaDelegate; englishPerson.eating(); Console.ReadLine(); } static void chineseEat(Person p) { Console.WriteLine("我是{0},我今年{1}歲了,我吃饅頭",p.Name,p.Age); } }}
在上面代碼中可以看到,執行個體化了兩個Person對象,chinesePerson、englishPerson。如果按照上一部落格委託的形式還是要new 一個委派物件,將委託和已定義好的函數關聯起來。ps:注意委託調用和函數的位置關係。
我們使用匿名方法的方式實現了上一篇部落格委託中要實現的功能。只是在englishPerson對象指定委託變數之前先聲明了一個匿名方法,這個函數的聲明周期也是很短的,然後又聲明了一個匿名方法直接賦值給englishPerson的委託。
從上面的兩個對象使用委託的比較,我們也可以看出匿名函數的好處。
1.代碼結構方面
按照上一部落格的方法,委派物件關聯已有的方法,這個在代碼結構上委派物件和方法是分離的,這個分離主義是代碼位置的分離,執行個體化委派物件可能會在一個方法裡面,而關聯的方法會是另一個方法,雖然都是在一個類中,但在方法比較多的類中,影響代碼檢視,查看的時候還要跳轉。而在匿名方法中,在調用的時候才會執行個體化,這樣委託方法和調用離得就很近,很容易查看。
2.聲明周期
對於一定義的方法,它是定義在類中,而匿名方法則是定義在調用的方法中,聲明周期短。對於不經常調用,可能只在這一個地方使用的關聯方法,沒有必要定義在類中。
三、Lamdba運算式
對於上面的匿名方法還有一個好處就是簡潔方便,也主要是協助有懶癌的小夥伴們,那可能有懶癌到晚期的會問還有沒有更簡潔方便的能多簡潔就多簡潔,於是乎Lamdba運算式出現了,它也是匿名方法。下面是它的格式:
(參數列表)=>運算式或語句塊
Lambda運算子:所有的lambda運算式都是用新的lambda運算子 " => ",可以叫他,“轉到”或者 “成為”。運算子將運算式分為兩部分,左邊指定輸入參數,右邊是lambda的主體。還是使用同一個例子稍微改動下代碼來說明下Lamdba運算式。
using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;namespace Delegate{ class Program { static void Main(string[] args) { Person chinesePerson = new Person("小明",25); //通過建構函式執行個體化對象 chinesePerson.eatFoodDelegate += new EatFoodDelegate(chineseEat); chinesePerson.eating(); Console.WriteLine("--------------------------------------"); Person englishPerson = new Person("Ivan",25); englishPerson.eatFoodDelegate = (Person p) => { Console.WriteLine("I‘m {0},I am {1} , I eat MianBao", p.Name, p.Age); }; englishPerson.eatFoodDelegate += (Person p) => { Console.WriteLine("I‘m {0},I am {1} , I eat PiSa", p.Name, p.Age); }; englishPerson.eating(); Console.ReadLine(); } static void chineseEat(Person p) { Console.WriteLine("我是{0},我今年{1}歲了,我吃饅頭",p.Name,p.Age); } }}
定義Person類就不貼了,上面主要是在englishPerson對象上,上面指定eatFoodDelegate委託的函數是使用Lamdba實現的。可以看到左邊是(Person p),右邊是代碼,中間是Lamdba運算子=>.用上面的與匿名方法的那個demo做比較發現這種方式更為簡潔方便。不用再使用delegate關鍵字建立匿名方法了。
對於泛型委派,就放在泛型部分來瞭解吧。
C#文法之匿名函數和Lambda運算式