本文將通過執行個體解析對c# 委託進行詳細介紹,具有很好的參考價值,下面跟著小編一起來看下吧
委託是一個類型。C#中的委託是物件導向的,並且它是型別安全的 當建立委託執行個體的時候,建立的執行個體會包含一個調用列表,在調用列表中可以包含多個方法。每個方法稱作一個調用實體。調用實體可以是靜態方法,也可以是執行個體方法。如果是執行個體方法,則該調用實體包含調用該執行個體方法的執行個體。委託並不關心它所調用方法所屬的類,它只關心被呼叫者法與委託的類型是否相容。 下面是代碼執行個體:
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 被調用,兩個實參相加的值是:{0}", a + b); } private void Show2(int a, int b) { Console.WriteLine("方法 Show2 被調用,兩個實參相加的值是:{0}", a + b); } private void Show3(int a, int b) { Console.WriteLine("方法 Show3 被調用,兩個實參相加的值是:{0}", a + b); } } public class Program { static void Main(string[] args) { Test myT = new Test(); myT.myDelegate(33, 22); Console.ReadKey(); } }}
這段代碼示範的是最簡單的一種委託形式。委託類型可以定義在類的外部,也可以定義在類的內部。 本段代碼是定義在類的外部。第 3 行代碼定義的就是一個委託類型,委託類型的關鍵字是 delegate,關鍵字前是委託類型的存取權限修飾符。關鍵字後是委託類型的傳回型別,這個傳回型別規定與委託類型相容 的方法的傳回型別必須與之相同。傳回型別之後是委託類型的名稱。接下來是形參列表,它指定與委託類 型相容的方法的參數類型和個數必須與之相同。第 5 行代碼定義了一個委託類型的變數,它是一個執行個體欄位,存取權限是 public 的。注意委託類型欄位的存取權限一定要比委託類型的存取權限低或與委託類型的存取權限相同才可以。第 9 行、第 12 行和第 15 行代碼定義了三個方法。其中第 9 行代碼是一個靜態方法。因為這段代碼示範的是最簡單的委託使用方法,所以只使用了其中的靜態方法。在第 6 行的構造方法中,執行個體化了委託類型的變數,注意為委託變數的調用列表添加方法,只需要向其構造方法中傳遞方法名稱即可。這是為委託添加調用方法的最基本的一種方法。第 21 行定義了 Test 類的一個執行個體,然後第 22 行調用了類的委託成員。在調用委託成員的時候,需要向其形參列表傳遞實參。這就是最基本的委託的使用方法。這段代碼的執行結果如下:
方法 Show1 被調用,兩個實參相加的值是:55
下面再介紹一種委託類型的使用方法,執行個體代碼如下:
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 被調用,兩個實參相加的值是:{0}", a + b); } public void Show2(int a, int b) { Console.WriteLine("方法 Show2 被調用,兩個實參相加的值是:{0}", a + b); } public void Show3(int a, int b) { Console.WriteLine("方法 Show3 被調用,兩個實參相加的值是:{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(); } }}
這段代碼取消了類中的委託類型欄位,而是將委託類型作為一個類來看待。在包含進入點方法的類中,首先第 17 行定義了 Test 類的一個變數並做了執行個體化。因為要向委託傳遞類的執行個體方法,所以必須有類的實 例存在,才能引用類的執行個體方法。第 18 行定義了一個委託類型的變數,並執行個體化,這裡需要注意,因為委託並不是類中的一個成員了, 所以向其構造方法傳遞靜態方法的時候,需要以類名引用。第 19 行也定義了一個委託類型的變數,在向其傳遞執行個體方法的時候,需要以類的執行個體來引用。第 20 行代碼的情況同第 19 行代碼一樣。在向委託傳遞方法的時候,需要傳遞方法名,而不需要方法的形參列表。第 21 行到第 23 行是對委託的調用,這時要為其傳遞方法的實參。這段代碼的執行結果如下:
方法 Show1 被調用,兩個實參相加的值是:55 方法 Show2 被調用,兩個實參相加的值是:77 方法 Show3 被調用,兩個實參相加的值是:121
委託的存取修飾詞
當委託位於類的外部時,可以使用的存取修飾詞包括 public 和 internal。如果什麼也不寫,預設是internal 的。當委託位於類的內部時,可以使用的存取修飾詞包括 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 被調用,兩個實參相加的值是:{0}", a + b); } public void Show2(int a, int b) { Console.WriteLine("方法 Show2 被調用,兩個實參相加的值是:{0}", a + b); } public void Show3(int a, int b) { Console.WriteLine("方法 Show3 被調用,兩個實參相加的值是:{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 行在類的內部定義了委託類型,它作為類的成員定義,存取權限是 protected,它可以被本類內部訪問,也可以被衍生類別訪問。代碼的第 5 行定義的委託類型,存取權限是 private 的,它只可以被本類內部訪問。代碼的第 6 行定義的 protected internal 存取權限的委託類型,可以被本程式集訪問, 還可以被衍生類別訪問,而不管衍生類別位於哪個程式集。第 7 行定義的委託類型是 internal 的,它只可以被本程式集訪問。因為所有這幾種委託類型都可以被本類內部訪問,所以第 10 行到第 13 行定義了它們的變數。第 12 行的執行個體構造方法中,對這四個委託類型的變數進行了執行個體化,並為它們的調用列表加入了方法 Show1。Show1 是一個靜態方法,但是在類內部傳入委託類型的構造方法時,不需要使用類名引用。第 27 行定義了執行個體方法,在方法內部調用了這四個委託,並為其傳入實參。第 34 行代碼又定義了一個類,它繼承自基類 Test。因為基類中的委託類型只有 D、D2 和 D3 可以被衍生類別訪問,所以第 35 行到第 37 行定義了它們的變數。注意,雖然它們和基類中的委託變數是同一種類型, 但是它們是不同的委託。在第 38 行的執行個體構造方法中,為這三個委託類型的變數建立執行個體,並為其調用列表加入方法,因為靜態方法 Show1 也被衍生類別所繼承,所以這裡傳入的方法名,可以使用類名引用,也可以不使用類名引用。 第 43 行定義了一個執行個體方法,方法內部調用了這三個委託,並為其傳入實參。第 51 行定義了衍生類別的執行個體,然後調用執行個體方法Use和Use1。這段代碼的執行結果如下:
方法 Show1 被調用,兩個實參相加的值是:23 方法 Show1 被調用,兩個實參相加的值是:67 方法 Show1 被調用,兩個實參相加的值是:133方法 Show1 被調用,兩個實參相加的值是:445 方法 Show1 被調用,兩個實參相加的值是:67 方法 Show1 被調用,兩個實參相加的值是:89 方法 Show1 被調用,兩個實參相加的值是:155
因為 D 和 D2 的存取權限被定義成了 protected 和 protected internal。所以下面來驗證在其它程式集中是否可以訪問它們。首先要將本段代碼中的包含 Main 方法的類去掉,然後在它的項目屬性中將它改變為類庫。接下來建立一個控制台項目,並物理上引用這個類庫。控制台項目的代碼如下:
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(); } }}
因為第 3 行代碼的命名空間和類庫的命名空間是兩個獨立的命名空間,它們的成員不位於同一個命名空間內。所以在一個命名空間內引用另一個命名空間的成員時,需要加上另一個命名空間的名稱進行引用。 為了代碼編寫的方便,第 2 行代碼首先引用了類庫的命名空間。第 4 行代碼定義了一個類,它繼承自基類 Test。因為是衍生類別,所以對於委託類型 D 和 D2 都可以訪 問。第 5 行代碼和第 6 行代碼分別定義了 D 和 D2 的兩個變數。第 7 行的執行個體構造方法對這兩個變數進行了執行個體化,並為其傳入方法 Show1。因為 Show1 方法被繼承了下來,所以這裡不需要類名引用。第 11 行代碼定義了一個執行個體方法,它的作用是調用這兩個委託,並為其傳入實參。第 16 行代碼定義了本類的一個執行個體,並調用了執行個體方法 Use3。這段代碼的執行結果如下:
方法 Show1 被調用,兩個實參相加的值是:67方法 Show1 被調用,兩個實參相加的值是:23
類Test中的委託類型D2和D3都具有internal許可權,現在來驗證一下,對於一個同一程式集中的非衍生類別是否可以訪問它們。首先將類庫更改回控制台項目,然後增加一個類,這個類對於Test類來說是獨立的。它們之間只是位於一個程式集內,彼此沒有繼承關係。代碼如下:
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 被調用,兩個實參相加的值是:{0}", a + b); } public void Show2(int a, int b) { Console.WriteLine("方法 Show2 被調用,兩個實參相加的值是:{0}", a + b); } public void Show3(int a, int b) { Console.WriteLine("方法 Show3 被調用,兩個實參相加的值是:{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(); } }}
這段代碼中,原來的類Test沒有進行修改。在第35行上,定義了一個類,它是一個相對於Test類來說獨立的類。它們的關係僅限於同在一個程式集內。第 36 行代碼和第 37 行代碼定義了委託類型D2和D3的兩個變數。這裡需要注意,因為這兩個類不是繼承關係,所以要引用Test類中的這兩個委託類型需要使用Test類的類名進行引用。第 38 行代碼是執行個體構造方法,在構造方法中將委託執行個體化。執行個體化委託類型的時候,仍然需要使用類名引用委託類型名,傳遞的方法名也是如此。第 行42 定義了一個執行個體方法,它調用了委託,並為其傳入了實參。第 49 行代碼定義了類Test1的一個執行個體,然後第 61 行調用類的執行個體方法。這段代碼的執行結果如下:
方法 Show1 被調用,兩個實參相加的值是:67方法 Show1 被調用,兩個實參相加的值是:43
以上就是c# 委託代碼執行個體詳解的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!