解析.Net 4.0 中委托delegate的使用詳解
一. 先來看下委托的定義:
如下C#代碼定義委托
public delegate void DoSomething(int times);
委托的定義包含5個部分
1) public表示委托的可訪問性
2) delegate關(guān)鍵字表示要定義一個委托
3) void表示委托定義方法的返回值
4) DoSomething是委托的名字
5) (int times) 是委托方法的參數(shù)列表,此處的參數(shù)列表可以包括ref參數(shù),也可以有out參數(shù),同樣也可以有parms可變數(shù)量參數(shù);需要注意如果委托中有多個調(diào)用方法,使用out參數(shù)時只能返回委托最后執(zhí)行成功的一個委托方法的計(jì)算值
在C#中定義委托非常簡單,只比方法定義的返回值之前多一個delegate關(guān)鍵字即可。
可是我們知道所有的用戶定義委托都繼承自MulticastDelegate;而MulticastDelegate是一個類;所以自定義的委托肯定也是一個類;看下上述代碼的IL代碼就可以證明我們的推斷:
.class public auto ansi sealed delegates.DoSomething
extends [mscorlib]System.MulticastDelegate
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
object 'object',
native int 'method'
) runtime managed
{
} // end of method DoSomething::.ctor
.method public hidebysig newslot virtual
instance void Invoke (
int32 times
) runtime managed
{
} // end of method DoSomething::Invoke
.method public hidebysig newslot virtual
instance class [mscorlib]System.IAsyncResult BeginInvoke (
int32 times,
class [mscorlib]System.AsyncCallback callback,
object 'object'
) runtime managed
{
} // end of method DoSomething::BeginInvoke
.method public hidebysig newslot virtual
instance void EndInvoke (
class [mscorlib]System.IAsyncResult result
) runtime managed
{
} // end of method DoSomething::EndInvoke
} // end of class delegates.DoSomething
二. 定義了委托,當(dāng)然是為了使用它,來看下如何使用委托:
在.Net中有三種委托的形式,分別是方法、匿名方法和lambda表達(dá)式;我們用方法定義的形式看下委托的使用方法
using System;
namespace delegates
{
public delegate void DoSomething(int times);
class Program
{
static void Main(string[] args)
{
//聲明委托變量并給委托變量賦值
DoSomething @do = DoA;
//可以使用+號或者+=給委托增加方法
@do += DoB;
//執(zhí)行委托時將按照委托的添加順序先后執(zhí)行委托中的方法
@do(1);
//也可以通過-號或者-= 從委托中移除方法
@do -= DoA;
@do(2);
@do -= DoB;
//將委托中的所有方法都移除掉之后,委托照樣是可以調(diào)用的,只是什么都不做
@do(3);
Console.Read();
}
//定義一個委托相同參數(shù)和返回值的方法
static void DoA(int times)
{
Console.WriteLine("Do A {0}", times);
}
//定義一個委托相同參數(shù)和返回值的方法
static void DoB(int times)
{
Console.WriteLine("Do B {0}", times);
}
}
}
如上代碼中的Main方法,首先我們定義了委托DoSomething的變量@do,并將DoA方法直接賦值給此委托變量;然后我們又使用+=符號或者+號給此委托添加了另一個方法;當(dāng)然也可以使用-或者-=從委托中去掉方法。
委托比C/C++方法指針強(qiáng)大的地方在于其可以容納多個方法,也可以執(zhí)行+/-操作從方法列表中添加或者刪除掉方法。
在執(zhí)行委托加減運(yùn)算時有幾個問題需要我們注意:
1. 委托聲明的寫法
委托聲明時可以用如下寫法
DoSomething @do = DoA;
這其實(shí)是一種簡短的寫法,我們知道在.Net 1.x中這樣寫是不允許的只有到.Net 2.0時才允許這么寫,在.Net 1.x中必須寫成
DoSomething @do = new DoSomething(DoA);
我們要在聲明時就給@do賦予DoA加上DoB
DoSomething @do = DoA + DoB;
這么寫是不行的,編譯器不干了;必須使用.Net 1.x中的寫法
DoSomething @do = new DoSomething(DoA) + new DoSomething(DoB);
2. 從委托中減去委托中本不存在的方式時會發(fā)生什么呢?
請看如下代碼:
DoSomething @do = DoA;
@do -= DoB;
第一行代碼我生命了@do并將DoA賦予它;第二行代碼我嘗試從@do中減去DoB,DoB并沒有在@do的方法列表中存在,這樣會發(fā)生什么情況呢?首先編譯器沒有報(bào)錯,程序可以正常的編譯;執(zhí)行代碼發(fā)現(xiàn)可以程序可以正常執(zhí)行,調(diào)用@do委托時正確的執(zhí)行了DoA方法;這說明了.Net包容了我們程序員犯的錯,我們從委托變量中減去一個委托中并不包含的方法時,不會報(bào)錯會正常的執(zhí)行。
3. 對委托做減法,所有委托都減完了,會怎樣呢?看如下代碼
DoSomething @do = new DoSomething(DoA) + new DoSomething(DoB);
@do -= DoA;
@do -= DoB;
@do(1);
這樣的代碼可以成功編譯,但是在運(yùn)行時會報(bào)NullReferenceException;這顯然不是我們希望的,所以對委托做減法時要特別注意。
<span style="text-decoration: line-through;">public delegate void DoIt(string task);
class Test
{
static void Main(string[] args)
{
//DoIt聲明,賦予一個參數(shù)更寬泛的方法是合法的
DoIt doIt = new DoIt(DoItImpl);
doIt("hello");
}
//比委托定義中的參數(shù)更寬泛,string類型可以隱式轉(zhuǎn)換成object
static void DoItImpl(object task)
{
Console.WriteLine("DoItImpl {0}",task);
}
}
</span>
相關(guān)文章
詳解Asp.Net Core 發(fā)布和部署( MacOS + Linux + Nginx )
這篇文章主要介紹了詳解Asp.Net Core 發(fā)布和部署( MacOS + Linux + Nginx ) ,具有一定的參考價值,有興趣的可以了解一下。2016-12-12asp.net中實(shí)體類對象賦值到表單的實(shí)現(xiàn)代碼
昨天在網(wǎng)上看到了一個利用反射表單賦值到實(shí)體類對象的一個方法,自己就在加了個方法,從實(shí)體對象到表單,覺的很不錯非常省事,所以把他寫成了一個類,供以后使用2010-11-11ASP.NET Core應(yīng)用錯誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)“開發(fā)者
這篇文章主要給大家介紹了關(guān)于ASP.NET Core應(yīng)用錯誤處理之DeveloperExceptionPageMiddleware中間件呈現(xiàn)“開發(fā)者異常頁面”的相關(guān)資料,需要的朋友可以參考下2019-01-01.NET?6新特性試用之DateOnly和TimeOnly類型
這篇文章主要介紹了.NET?6新特性試用之DateOnly和TimeOnly類型,主要介紹DateOnly和TimeOnly類型使用過程及存在的一些過程,需要的小伙伴可以參考一下2022-03-03ASP.NET連接數(shù)據(jù)庫并獲取數(shù)據(jù)方法總結(jié)
這篇文章主要介紹了ASP.NET連接數(shù)據(jù)庫并獲取數(shù)據(jù)方法,結(jié)合實(shí)例分析總結(jié)了ASP.NET連接數(shù)據(jù)庫及獲取數(shù)據(jù)的相關(guān)實(shí)現(xiàn)技巧,并附帶了web.config配置文件的使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2015-11-11ASP.NET MVC5網(wǎng)站開發(fā)概述(一)
這篇文章主要內(nèi)容是ASP.NET MVC5網(wǎng)站開發(fā)實(shí)踐的整體概述,分析了開發(fā)環(huán)境、使用的技術(shù)以及項(xiàng)目的整體結(jié)構(gòu),感興趣的小伙伴們可以參考一下2015-09-09.Net Core3.0 WEB API中使用FluentValidation驗(yàn)證(批量注入)
這篇文章主要介紹了.Net Core3.0 WEB API中使用FluentValidation驗(yàn)證(批量注入),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12ASP.NET設(shè)置404頁面返回302HTTP狀態(tài)碼的解決方法
訪問網(wǎng)站時錯誤頁面可正常顯示,但HTTP狀態(tài)碼卻是302,對SEO很不友好,按下列步驟修改使錯誤頁面返回正確的利于SEO的404狀態(tài)碼,感興趣的朋友可以了解下2013-09-09