c# 委托詳解
委托是一個(gè)類型。C#中的委托是面向?qū)ο蟮?,并且它是類?a href='http://www.jygsgssxh.com/dedecms_aq/' target='_blank'>安全的 當(dāng)創(chuàng)建委托實(shí)例的時(shí)候,創(chuàng)建的實(shí)例會(huì)包含一個(gè)調(diào)用列表,在調(diào)用列表中可以包含多個(gè)方法。每個(gè)方法稱作一個(gè)調(diào)用實(shí)體。調(diào)用實(shí)體可以是靜態(tài)方法,也可以是實(shí)例方法。如果是實(shí)例方法,則該調(diào)用實(shí)體包含調(diào)用該實(shí)例方法的實(shí)例。委托并不關(guān)心它所調(diào)用方法所屬的類,它只關(guān)心被調(diào)用方法與委托的類型是否兼容。 下面是代碼實(shí)例:
using System;
namespace LycheeTest{
public delegate void D(int a, int b);
public class Test {
public D myDelegate;
public Test() {
myDelegate = new D(Show1);
}
private static void Show1(int a, int b) {
Console.WriteLine("方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
private void Show2(int a, int b) {
Console.WriteLine("方法 Show2 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
private void Show3(int a, int b) {
Console.WriteLine("方法 Show3 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
}
public class Program {
static void Main(string[] args) {
Test myT = new Test();
myT.myDelegate(33, 22);
Console.ReadKey();
}
}
}
這段代碼演示的是最簡(jiǎn)單的一種委托形式。委托類型可以定義在類的外部,也可以定義在類的內(nèi)部。 本段代碼是定義在類的外部。第 3 行代碼定義的就是一個(gè)委托類型,委托類型的關(guān)鍵字是 delegate,關(guān)鍵字前是委托類型的訪問(wèn)權(quán)限修飾符。關(guān)鍵字后是委托類型的返回類型,這個(gè)返回類型規(guī)定與委托類型兼容 的方法的返回類型必須與之相同。返回類型之后是委托類型的名稱。接下來(lái)是形參列表,它指定與委托類 型兼容的方法的參數(shù)類型和個(gè)數(shù)必須與之相同。第 5 行代碼定義了一個(gè)委托類型的變量,它是一個(gè)實(shí)例字段,訪問(wèn)權(quán)限是 public 的。注意委托類型字段的訪問(wèn)權(quán)限一定要比委托類型的訪問(wèn)權(quán)限低或與委托類型的訪問(wèn)權(quán)限相同才可以。第 9 行、第 12 行和第 15 行代碼定義了三個(gè)方法。其中第 9 行代碼是一個(gè)靜態(tài)方法。因?yàn)檫@段代碼演示的是最簡(jiǎn)單的委托使用方法,所以只使用了其中的靜態(tài)方法。在第 6 行的構(gòu)造方法中,實(shí)例化了委托類型的變量,注意為委托變量的調(diào)用列表添加方法,只需要向其構(gòu)造方法中傳遞方法名稱即可。這是為委托添加調(diào)用方法的最基本的一種方法。第 21 行定義了 Test 類的一個(gè)實(shí)例,然后第 22 行調(diào)用了類的委托成員。在調(diào)用委托成員的時(shí)候,需要向其形參列表傳遞實(shí)參。這就是最基本的委托的使用方法。這段代碼的執(zhí)行結(jié)果如下:
方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:55
下面再介紹一種委托類型的使用方法,實(shí)例代碼如下:
using System;
namespace LycheeTest {
public delegate void D(int a, int b);
public class Test {
public static void Show1(int a, int b) {
Console.WriteLine("方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
public void Show2(int a, int b) {
Console.WriteLine("方法 Show2 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
public void Show3(int a, int b) {
Console.WriteLine("方法 Show3 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
}
public class Program {
static void Main(string[] args) {
Test myT = new Test();
D myDelegate = new D(Test.Show1);
D myDelegate1 = new D(myT.Show2);
D myDelegate2 = new D(myT.Show3);
myDelegate(22, 33);
myDelegate1(33, 44);
myDelegate2(55, 66);
Console.ReadKey();
}
}
}
這段代碼取消了類中的委托類型字段,而是將委托類型作為一個(gè)類來(lái)看待。在包含入口點(diǎn)方法的類中,首先第 17 行定義了 Test 類的一個(gè)變量并做了實(shí)例化。因?yàn)橐蛭袀鬟f類的實(shí)例方法,所以必須有類的實(shí) 例存在,才能引用類的實(shí)例方法。第 18 行定義了一個(gè)委托類型的變量,并實(shí)例化,這里需要注意,因?yàn)槲胁⒉皇穷愔械囊粋€(gè)成員了, 所以向其構(gòu)造方法傳遞靜態(tài)方法的時(shí)候,需要以類名引用。第 19 行也定義了一個(gè)委托類型的變量,在向其傳遞實(shí)例方法的時(shí)候,需要以類的實(shí)例來(lái)引用。第 20 行代碼的情況同第 19 行代碼一樣。在向委托傳遞方法的時(shí)候,需要傳遞方法名,而不需要方法的形參列表。第 21 行到第 23 行是對(duì)委托的調(diào)用,這時(shí)要為其傳遞方法的實(shí)參。這段代碼的執(zhí)行結(jié)果如下:
方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:55 方法 Show2 被調(diào)用,兩個(gè)實(shí)參相加的值是:77 方法 Show3 被調(diào)用,兩個(gè)實(shí)參相加的值是:121
委托的訪問(wèn)修飾符
當(dāng)委托位于類的外部時(shí),可以使用的訪問(wèn)修飾符包括 public 和 internal。如果什么也不寫,默認(rèn)是internal 的。當(dāng)委托位于類的內(nèi)部時(shí),可以使用的訪問(wèn)修飾符包括 public、protected、internal、protected
using System;
namespace LycheeTest{
public class Test {
protected delegate void D(int a, int b);
private delegate void D1(int a, int b);
protected internal delegate void D2(int a, int b);
internal delegate void D3(int a, int b);
private D myD;
private D1 myD1;
private D2 myD2;
private D3 myD3;
public Test() {
myD = new D(Show1);
myD1 = new D1(Show1);
myD2 = new D2(Show1);
myD3 = new D3(Show1);
}
public static void Show1(int a, int b) {
Console.WriteLine("方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
public void Show2(int a, int b) {
Console.WriteLine("方法 Show2 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
public void Show3(int a, int b) {
Console.WriteLine("方法 Show3 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
public void Use() {
myD(11, 12);
myD1(22, 45);
myD2(55, 78);
myD3(345, 100);
}
}
class Test1: Test {
private D Test1D;
private D2 Test1D2;
private D3 Test1D3;
public Test1() {
Test1D = new D(Test.Show1);
Test1D2 = new D2(Test.Show1);
Test1D3 = new D3(Test.Show1);
}
public void Use1() {
Test1D(22, 45);
Test1D2(44, 45);
Test1D3(77, 78);
}
}
public class Program {
static void Main(string[] args) {
Test1 myT1 = new Test1();
myT1.Use();
myT1.Use1();
Console.ReadKey();
}
}
}
代碼的第 4 行在類的內(nèi)部定義了委托類型,它作為類的成員定義,訪問(wèn)權(quán)限是 protected,它可以被本類內(nèi)部訪問(wèn),也可以被派生類訪問(wèn)。代碼的第 5 行定義的委托類型,訪問(wèn)權(quán)限是 private 的,它只可以被本類內(nèi)部訪問(wèn)。代碼的第 6 行定義的 protected internal 訪問(wèn)權(quán)限的委托類型,可以被本程序集訪問(wèn), 還可以被派生類訪問(wèn),而不管派生類位于哪個(gè)程序集。第 7 行定義的委托類型是 internal 的,它只可以被本程序集訪問(wèn)。因?yàn)樗羞@幾種委托類型都可以被本類內(nèi)部訪問(wèn),所以第 10 行到第 13 行定義了它們的變量。第 12 行的實(shí)例構(gòu)造方法中,對(duì)這四個(gè)委托類型的變量進(jìn)行了實(shí)例化,并為它們的調(diào)用列表加入了方法 Show1。Show1 是一個(gè)靜態(tài)方法,但是在類內(nèi)部傳入委托類型的構(gòu)造方法時(shí),不需要使用類名引用。第 27 行定義了實(shí)例方法,在方法內(nèi)部調(diào)用了這四個(gè)委托,并為其傳入實(shí)參。第 34 行代碼又定義了一個(gè)類,它繼承自基類 Test。因?yàn)榛愔械奈蓄愋椭挥?D、D2 和 D3 可以被派生類訪問(wèn),所以第 35 行到第 37 行定義了它們的變量。注意,雖然它們和基類中的委托變量是同一種類型, 但是它們是不同的委托。在第 38 行的實(shí)例構(gòu)造方法中,為這三個(gè)委托類型的變量創(chuàng)建實(shí)例,并為其調(diào)用列表加入方法,因?yàn)殪o態(tài)方法 Show1 也被派生類所繼承,所以這里傳入的方法名,可以使用類名引用,也可以不使用類名引用。 第 43 行定義了一個(gè)實(shí)例方法,方法內(nèi)部調(diào)用了這三個(gè)委托,并為其傳入實(shí)參。第 51 行定義了派生類的實(shí)例,然后調(diào)用實(shí)例方法Use和Use1。這段代碼的執(zhí)行結(jié)果如下:
方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:23 方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:67 方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:133 方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:445 方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:67 方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:89 方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:155
因?yàn)?D 和 D2 的訪問(wèn)權(quán)限被定義成了 protected 和 protected internal。所以下面來(lái)驗(yàn)證在其它程序集中是否可以訪問(wèn)它們。首先要將本段代碼中的包含 Main 方法的類去掉,然后在它的項(xiàng)目屬性中將它改變?yōu)轭悗?kù)。接下來(lái)新建一個(gè)控制臺(tái)項(xiàng)目,并物理上引用這個(gè)類庫(kù)??刂婆_(tái)項(xiàng)目的代碼如下:
using System;
using LycheeTest;
namespace LycheeTest1{
class Program: Test {
private D pD;
private D2 pD2;
public Program() {
pD = new D(Show1);
pD2 = new D2(Show1);
}
public void Use3() {
pD(34, 33);
pD2(12, 11);
}
static void Main(string[] args) {
Program p = new Program();
p.Use3();
Console.ReadKey();
}
}
}
因?yàn)榈?3 行代碼的命名空間和類庫(kù)的命名空間是兩個(gè)獨(dú)立的命名空間,它們的成員不位于同一個(gè)命名空間內(nèi)。所以在一個(gè)命名空間內(nèi)引用另一個(gè)命名空間的成員時(shí),需要加上另一個(gè)命名空間的名稱進(jìn)行引用。 為了代碼編寫的方便,第 2 行代碼首先引用了類庫(kù)的命名空間。第 4 行代碼定義了一個(gè)類,它繼承自基類 Test。因?yàn)槭桥缮?,所以?duì)于委托類型 D 和 D2 都可以訪 問(wèn)。第 5 行代碼和第 6 行代碼分別定義了 D 和 D2 的兩個(gè)變量。第 7 行的實(shí)例構(gòu)造方法對(duì)這兩個(gè)變量進(jìn)行了實(shí)例化,并為其傳入方法 Show1。因?yàn)?Show1 方法被繼承了下來(lái),所以這里不需要類名引用。第 11 行代碼定義了一個(gè)實(shí)例方法,它的作用是調(diào)用這兩個(gè)委托,并為其傳入實(shí)參。第 16 行代碼定義了本類的一個(gè)實(shí)例,并調(diào)用了實(shí)例方法 Use3。這段代碼的執(zhí)行結(jié)果如下:
方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:67 方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:23
類Test中的委托類型D2和D3都具有internal權(quán)限,現(xiàn)在來(lái)驗(yàn)證一下,對(duì)于一個(gè)同一程序集中的非派生類是否可以訪問(wèn)它們。首先將類庫(kù)更改回控制臺(tái)項(xiàng)目,然后增加一個(gè)類,這個(gè)類對(duì)于Test類來(lái)說(shuō)是獨(dú)立的。它們之間只是位于一個(gè)程序集內(nèi),彼此沒(méi)有繼承關(guān)系。代碼如下:
using System;
namespace LycheeTest {
public class Test {
protected delegate void D(int a, int b);
private delegate void D1(int a, int b);
protected internal delegate void D2(int a, int b);
internal delegate void D3(int a, int b);
private D myD;
private D1 myD1;
private D2 myD2;
private D3 myD3;
public Test() {
myD = new D(Show1);
myD1 = new D1(Show1);
myD2 = new D2(Show1);
myD3 = new D3(Show1);
}
public static void Show1(int a, int b) {
Console.WriteLine("方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
public void Show2(int a, int b) {
Console.WriteLine("方法 Show2 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
public void Show3(int a, int b) {
Console.WriteLine("方法 Show3 被調(diào)用,兩個(gè)實(shí)參相加的值是:{0}", a + b);
}
public void Use() {
myD(11, 12);
myD1(22, 45);
myD2(55, 78);
myD3(345, 100);
}
}
class Test1 {
private Test.D2 tD2;
private Test.D3 tD3;
public Test1() {
tD2 = new Test.D2(Test.Show1);
tD3 = new Test.D3(Test.Show1);
}
public void Use3() {
tD2(34, 33);
tD3(22, 21);
}
}
public class Program {
static void Main(string[] args) {
Test1 myT1 = new Test1();
myT1.Use3();
Console.ReadKey();
}
}
}
這段代碼中,原來(lái)的類Test沒(méi)有進(jìn)行修改。在第35行上,定義了一個(gè)類,它是一個(gè)相對(duì)于Test類來(lái)說(shuō)獨(dú)立的類。它們的關(guān)系僅限于同在一個(gè)程序集內(nèi)。第 36 行代碼和第 37 行代碼定義了委托類型D2和D3的兩個(gè)變量。這里需要注意,因?yàn)檫@兩個(gè)類不是繼承關(guān)系,所以要引用Test類中的這兩個(gè)委托類型需要使用Test類的類名進(jìn)行引用。第 38 行代碼是實(shí)例構(gòu)造方法,在構(gòu)造方法中將委托實(shí)例化。實(shí)例化委托類型的時(shí)候,仍然需要使用類名引用委托類型名,傳遞的方法名也是如此。第 行42 定義了一個(gè)實(shí)例方法,它調(diào)用了委托,并為其傳入了實(shí)參。第 49 行代碼定義了類Test1的一個(gè)實(shí)例,然后第 61 行調(diào)用類的實(shí)例方法。這段代碼的執(zhí)行結(jié)果如下:
方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:67 方法 Show1 被調(diào)用,兩個(gè)實(shí)參相加的值是:43
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,同時(shí)也希望多多支持我們!
上一篇:asp.net core mvc權(quán)限控制:在視圖中控制操作權(quán)限
欄 目:C#教程
下一篇:C#實(shí)現(xiàn)char字符數(shù)組與字符串相互轉(zhuǎn)換的方法
本文標(biāo)題:c# 委托詳解
本文地址:http://www.jygsgssxh.com/a1/C_jiaocheng/5929.html
您可能感興趣的文章
- 01-10C#中Socket通信用法實(shí)例詳解
- 01-10C#裝箱和拆箱原理詳解
- 01-10C#類的多態(tài)性詳解
- 01-10C#創(chuàng)建不規(guī)則窗體的4種方式詳解
- 01-10C#中深度復(fù)制和淺度復(fù)制詳解
- 01-10C#基于委托實(shí)現(xiàn)多線程之間操作的方法
- 01-10C#數(shù)據(jù)結(jié)構(gòu)之隊(duì)列(Quene)實(shí)例詳解
- 01-10C#數(shù)據(jù)結(jié)構(gòu)之順序表(SeqList)實(shí)例詳解
- 01-10C#編程實(shí)現(xiàn)連接ACCESS數(shù)據(jù)庫(kù)實(shí)例詳解
- 01-10C#數(shù)據(jù)結(jié)構(gòu)之單鏈表(LinkList)實(shí)例詳解


閱讀排行
- 1C語(yǔ)言 while語(yǔ)句的用法詳解
- 2java 實(shí)現(xiàn)簡(jiǎn)單圣誕樹(shù)的示例代碼(圣誕
- 3利用C語(yǔ)言實(shí)現(xiàn)“百馬百擔(dān)”問(wèn)題方法
- 4C語(yǔ)言中計(jì)算正弦的相關(guān)函數(shù)總結(jié)
- 5c語(yǔ)言計(jì)算三角形面積代碼
- 6什么是 WSH(腳本宿主)的詳細(xì)解釋
- 7C++ 中隨機(jī)函數(shù)random函數(shù)的使用方法
- 8正則表達(dá)式匹配各種特殊字符
- 9C語(yǔ)言十進(jìn)制轉(zhuǎn)二進(jìn)制代碼實(shí)例
- 10C語(yǔ)言查找數(shù)組里數(shù)字重復(fù)次數(shù)的方法
本欄相關(guān)
- 01-10C#通過(guò)反射獲取當(dāng)前工程中所有窗體并
- 01-10關(guān)于ASP網(wǎng)頁(yè)無(wú)法打開(kāi)的解決方案
- 01-10WinForm限制窗體不能移到屏幕外的方法
- 01-10WinForm繪制圓角的方法
- 01-10C#實(shí)現(xiàn)txt定位指定行完整實(shí)例
- 01-10WinForm實(shí)現(xiàn)仿視頻播放器左下角滾動(dòng)新
- 01-10C#停止線程的方法
- 01-10C#實(shí)現(xiàn)清空回收站的方法
- 01-10C#通過(guò)重寫Panel改變邊框顏色與寬度的
- 01-10C#實(shí)現(xiàn)讀取注冊(cè)表監(jiān)控當(dāng)前操作系統(tǒng)已
隨機(jī)閱讀
- 01-10delphi制作wav文件的方法
- 01-10C#中split用法實(shí)例總結(jié)
- 01-10使用C語(yǔ)言求解撲克牌的順子及n個(gè)骰子
- 08-05dedecms(織夢(mèng))副欄目數(shù)量限制代碼修改
- 08-05織夢(mèng)dedecms什么時(shí)候用欄目交叉功能?
- 01-11ajax實(shí)現(xiàn)頁(yè)面的局部加載
- 08-05DEDE織夢(mèng)data目錄下的sessions文件夾有什
- 04-02jquery與jsp,用jquery
- 01-11Mac OSX 打開(kāi)原生自帶讀寫NTFS功能(圖文
- 01-10SublimeText編譯C開(kāi)發(fā)環(huán)境設(shè)置


