C#委托與匿名委托詳解
本來是想寫一篇《委托與lambda表達式的前世今生》,但僅委托部分已經(jīng)寫了很多內(nèi)容,于是就此分開關于Lambda表達是的內(nèi)容后續(xù)再寫吧。
不知道Lambda表達式是誰發(fā)明的,只記得第一次接觸Lambda表達式是在使用VS2008的時候,那就先認為是微軟發(fā)明的吧。
Lambda表達式從我接觸開始到現(xiàn)在變得越來越流行,Java8中開始支持、kotlin更是對C#,F(xiàn)#做了廣泛的抄襲(C#曾幾何時不也如此對待過Java嘛)。其實這都充分說明了,Lambda表達式的重要性。要搞清楚Lambda首先需要搞清楚委托。
委托:
假設現(xiàn)在我們要開發(fā)一個處理兩個整數(shù)的程序(假設先處理相加操作)
public class Worker { /// <summary> /// 處理兩個數(shù) /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> public int HandleTwoNumber(int a,int b) { return a + b; } } static void Main(string[] args) { int a = int.Parse(Console.ReadLine()); int b = int.Parse(Console.ReadLine()); Worker worker = new Worker(); int result = worker.HandleTwoNumber(a, b); Console.WriteLine(String.Format("Result:{0}", result)); string p = Console.ReadLine(); }
如果一段時間后,我們需要它變更為減操作:
public class Worker { public int HandleTwoNumber(int a,int b) { return a - b; } }
雖然有a+b變?yōu)閍-b的變化很微小,但后續(xù)此處可能面臨多次變化(由減變?yōu)槌?........)。有變化就應封裝變化,此處我們可以將a與b的操作行為抽象出來,用什么抽象呢?委托
public class Worker { public delegate int TwoNumberHandleMethodDelegate(int x, int y); public int HandleTwoNumber(int a,int b) { return a + b; } }
public delegate int TwoNumberHandleMethodDelegate(int x, int y);此處用delegate標注,表明這是一個委托定義。如果去掉 delegate 再來觀察該定義,你會發(fā)現(xiàn)這就是一個沒有方法體的抽象方法。所以委托的含義即:與該抽象方法簽名形式相同的方法的類型。委托就是一種你定義的新數(shù)據(jù)類型,它與int、class是一樣的都是數(shù)據(jù)類型。int表示整數(shù),只要是整數(shù)都可以賦值給 int型變量;TwoNumberHandleMethodDelegate則表示,接收兩個int型參數(shù)并返回int型結(jié)果的這類方法,因此滿足上述要求的方法都可賦值給TwoNumberHandleMethodDelegate類型的變量。
如此一來Worker代碼可修改為:
public class Worker { public delegate int TwoNumberHandleMethodDelegate(int x, int y); public int HandleTwoNumber(int a, int b, TwoNumberHandleMethodDelegate handle) { return handle(a, b); } }
如此a、b的操作被封裝起來,所有的變化均交由調(diào)用者來處理。此處的含義:HandleTwoNumber處理a、b兩個整數(shù),具體如何處理由 handle 實施。此時你可能會問,那如何來調(diào)用該方法呢?調(diào)用如下:
private static int Add(int a, int b) { return a + b; } private static int Sub(int a, int b) { return a - b; } static void Main(string[] args) { int a = int.Parse(Console.ReadLine()); int b = int.Parse(Console.ReadLine()); Worker.TwoNumberHandleMethodDelegate method = new Worker.TwoNumberHandleMethodDelegate(Add); Worker worker = new Worker(); int result = worker.HandleTwoNumber(10, 10,method); //int result = worker.HandleTwoNumber(10, 10, Sub);//簡化版 Console.WriteLine(String.Format("Result:{0}", result)); }
根據(jù)上面的程序可知,Main代碼塊為worker的調(diào)用者,作為調(diào)用者而言應該最清楚自己想要讓woker做的工作。因此作為被調(diào)用者的worker而言,它只需要接收調(diào)用者Main給的a\b參數(shù)及執(zhí)行Main定制的算法method,然后按照算法執(zhí)行并返回結(jié)果即可。上面代碼雖然簡單,但其中的意義深遠,隨著編程時間的增加相信你的理解將越深刻。
委托變量在進行賦值時除了標準的方式,還可以進行簡化:
Worker.TwoNumberHandleMethodDelegate method = new Worker.TwoNumberHandleMethodDelegate(Add); Worker worker = new Worker(); int result = worker.HandleTwoNumber(10, 10,method); //可簡化為 // int result = worker.HandleTwoNumber(10, 10,Add);
編譯器將自動檢查Add是否符合 TwoNumberHandleMethodDelegate 的定義,如果符合允許直接將方法名賦值給委托變量。
匿名委托
通過上面的示例代碼,我們很容易發(fā)現(xiàn) TwoNumberHandleMethodDelegate method 變量被賦值為Add(Sub),因此在調(diào)用method(...)時相當于調(diào)用Add(.....)。這樣一來就可以認為
method與Add完全等效,既然等效那是否可以直接將Add的定義內(nèi)容賦值給method變量呢?答案是肯定的:
static void Main(string[] args) { Worker.TwoNumberHandleMethodDelegate method =private static int Add(int a, int b) { return a + b; }; }
但像上面這種生拉硬套是不行的,你還需要做修改。修改內(nèi)容是:因為現(xiàn)在的代碼處于Main方法中,訪問修飾符去掉,同樣static也應去掉;同時編譯器知道你要給method賦值,那么要賦的這個值肯定滿足返回類型為int的要求,所有int在此時就多余了去掉;因為賦值之后method就等效于Add,以后調(diào)用只要通過method變量就可完成,所有Add方法名不需要去掉。如此代碼變?yōu)槿缦滦问剑?/p>
static void Main(string[] args) { Worker.TwoNumberHandleMethodDelegate method = (int a, int b) { return a + b; }; }
經(jīng)過上面的修改內(nèi)容簡化了很多,但method賦值的=右端是什么東西呢?此時編譯器并不能正確識別這是一個方法,因為方法的定義需要滿足包含:訪問修身符、返回類型、方法名、參數(shù)列表、方法體五部分內(nèi)容。雖然你心里清楚這是個簡化了的方法,但是編譯器不懂你的心.........,那沒關系只要我們告訴編譯器,后面的是個簡化方法就可以了。
static void Main(string[] args) { Worker.TwoNumberHandleMethodDelegate method = delegate(int a, int b) { return a + b; }; }
正如你所期望的那樣,現(xiàn)在編譯器已經(jīng)知道了=右側(cè)是你經(jīng)過簡化的方法;ok,現(xiàn)在可以正常賦值并使用了。
通過上面的定義我們發(fā)現(xiàn),用delegate標注的簡化方法沒有一個像Add/Sub一樣固定的名字。因此我們稱這種方法叫匿名委托(我習慣稱匿名方法)。
你可能還注意到該匿名委托定義完畢后就賦值給Main代碼快中的局部變量method,因此當超出method的作用域后,該方法就再也沒有機會調(diào)用了。這引出了匿名方法、匿名委托、匿名函數(shù)它們的最常見用法,即用來定義只需要使用一次的功能代碼。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持我們。
上一篇:淺析C#中靜態(tài)方法和非靜態(tài)方法的區(qū)別
欄 目:C#教程
下一篇:C#實現(xiàn)動態(tài)數(shù)據(jù)繪圖graphic的方法示例
本文標題:C#委托與匿名委托詳解
本文地址:http://mengdiqiu.com.cn/a1/C_jiaocheng/5502.html
您可能感興趣的文章
- 01-10C#通過重寫Panel改變邊框顏色與寬度的方法
- 01-10C#實現(xiàn)實體類與字符串互相轉(zhuǎn)換的方法
- 01-10C#實現(xiàn)子窗體與父窗體通信方法實例總結(jié)
- 01-10時間戳與時間相互轉(zhuǎn)換(php .net精確到毫秒)
- 01-10基于C#實現(xiàn)簡單離線注冊碼生成與驗證
- 01-10C#開發(fā)中的垃圾回收機制簡析
- 01-10C#基于委托實現(xiàn)多線程之間操作的方法
- 01-10C#編程實現(xiàn)對象與JSON串互相轉(zhuǎn)換實例分析
- 01-10C#警惕匿名方法造成的變量共享實例分析
- 01-10C#多線程編程之使用ReaderWriterLock類實現(xiàn)多用戶讀與單用戶寫同步


閱讀排行
本欄相關
- 01-10C#通過反射獲取當前工程中所有窗體并
- 01-10關于ASP網(wǎng)頁無法打開的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實現(xiàn)txt定位指定行完整實例
- 01-10WinForm實現(xiàn)仿視頻播放器左下角滾動新
- 01-10C#停止線程的方法
- 01-10C#實現(xiàn)清空回收站的方法
- 01-10C#通過重寫Panel改變邊框顏色與寬度的
- 01-10C#實現(xiàn)讀取注冊表監(jiān)控當前操作系統(tǒng)已
隨機閱讀
- 04-02jquery與jsp,用jquery
- 01-10delphi制作wav文件的方法
- 01-11Mac OSX 打開原生自帶讀寫NTFS功能(圖文
- 08-05DEDE織夢data目錄下的sessions文件夾有什
- 01-10C#中split用法實例總結(jié)
- 08-05織夢dedecms什么時候用欄目交叉功能?
- 01-10SublimeText編譯C開發(fā)環(huán)境設置
- 01-11ajax實現(xiàn)頁面的局部加載
- 01-10使用C語言求解撲克牌的順子及n個骰子
- 08-05dedecms(織夢)副欄目數(shù)量限制代碼修改