上一篇博客主要是對委托和事件做了一小結,這篇是在上一篇博客的基礎上對匿名函數和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關鍵字創建匿名方法了。
對於泛型委托,就放在泛型部分來了解吧。