一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C# - C#沉淀之委托的深入講解

C#沉淀之委托的深入講解

2022-03-01 14:26東南有大樹 C#

如果要給方法傳遞一個方法參數時,就可以使用委托。下面這篇文章主要給大家介紹了關于C#沉淀之委托的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考下

什么是委托

要傳遞方法,就必須把方法的細節封裝在一鐘新類型的對象中,即委托。委托是一種特殊類型的對象,其特殊之處在于,我們以前定義的所有對象都包含數據,而委托只包含一個或多個方法的地址。

.NET版本中,委托指向方法的地址。在C++中,函數指針是一個指向內存位置的指針,但它不是類型安全的。開發者無法判斷這個指針實際指向什么,像參數和返回值等項就更不知道了。

.NET委托是類型安全的類,它定義了返回類型和參數的類型。委托類不僅包含對方法的引用,也可以包含對多個方法的引用。

可以認為委托是持有一個或多個方法的對象。委托可以被執行,執行委托時委托會執行它所“持有”的方法

代碼示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CodeForDelegate
{
 //使用關鍵字delegate聲明委托類型
 //委托是一種類型,所以它與類屬于同一級別
 //注意:這里是委托類型,而不是委托對象
 delegate void MyDel(int value);
 
 class Program
 {
 
  void PrintLow(int value)
  {
   Console.WriteLine("{0} - Low Value", value);
  }
 
  void PrintHigh(int value)
  {
   Console.WriteLine("{0} - High Value", value);
  }
 
  static void Main(string[] args)
  {
   //實例化Program類,以訪問PrintLow和PrintHigh方法
   Program program = new Program();
 
   //聲明一個MyDel類型的委托
   MyDel del;
 
   //創建隨機數
   Random rand = new Random();
   int randomvalue = rand.Next(99);
 
   //使用三目運算符根據當前隨機數的值來創建委托對象
   del = randomvalue < 50
    ? new MyDel(program.PrintLow)
    : new MyDel(program.PrintHigh);
 
   //執行委托
   del(randomvalue);
 
   Console.ReadKey();
  }
 }
}

從上例可以看出,使用委托的首先得通過關鍵字delegate聲明一個委托類型,這個委托類型包括返回值、名稱、簽名;當類型聲明好以后,需要通過new來創建委托對象,創建對象時的參數是一個方法,這個方法的簽名和返回類型必須與該委托類型定義的簽名一致;調用委托時,直接通過實例化的委托對象名,并提供參數即可,然后委托會執行在其所持有的方法

委托與類

委托和類一樣,是一種用戶自定義的類型;不同的是類表示的是數據和方法的集合,而委托持有一個或多個方法,以及一系列預定義操作

委托的使用步驟

  • 聲明一個委托類型
  • 使用該委托類型聲明一個委托變量
  • 創建委托類型的對象,把它賦值給委托變量;委托對象中包括指向某個方法的引用,此方法和委托類型定義的簽名與返回類型需要一致
  • 增加更多的方法(可選)
  • 像調用方法一樣調用委托(委托中的包含的每一個方法都會被執行)

delegate的原則

delegate相當于一個包含有序方法列表的對象,這些方法都具有相同的簽名和返回類型

方法的列表稱為調用列表

委托保存的方法可以來自任何類或結構,只要它們在以下兩點匹配:

  • 委托的返回類型
  • 委托的簽名(包括ref和out修飾符)

調用列表中的方法可以是靜態方法也可以是實例方法

在調用委托的時候,會調用列表中的所有方法

聲明委托類型

如下,delegate關鍵字開關,然后是返回類型,再定義名稱與簽名

?
1
delegate void MyDel(int vallue);

返回類型與簽名指定了委托接受的方法形式

注意:委托類型是沒有方法主體的

創建委托對象

使用new運算符創建對象

?
1
2
MyDel del = new MyDel(object.Func); //object.Func是個實例方法
Mydel _del = new MyDel(Object.Func); //Object.Func是個靜態方法

使用快捷語法創建對象

?
1
2
MyDel del = object.Func; //object.Func是個實例方法
Mydel _del = Object.Func; //Object.Func是個靜態方法

這種語法是能夠工作是因為在方法名稱和其相應的委托類型之間存在隱式的轉換

創建委托對象后會將指定的方法加入到委托的調用列表中

由于委托是引用類型,可以通過賦值來改變包含在委托變量中的引用,如下:

?
1
2
3
MyDel del;
del = new MyDel(object.FuncA); //創建第一個對象
del = new MyDel(object.FuncB); //創建第二個對象

由于第二個對象也賦值給了變量del,因此del所引用的第一個對象將被垃圾回收器回收

組合委托

?
1
2
3
4
5
6
//創建兩個委托
MyDel del_A = new MyDel(object.FuncA);
Mydel del_B = new MyDel(object.FuncA);
 
//組合委托
MyDel del_C = del_A + del_B;

當將del_A與del_B通過+進行組合后,會返回一個新的委托對象,該對象將del_A與del_B中的方法調用列表組合到新的對象里,該新對象賦值給變量del_C,所以執行del_C的時候,會執行del_A與del_B中所保存的方法object.FuncA和object.FuncA

委托添加多個方法

?
1
2
3
MyDel del = object.FuncA; //創建并初始化委托對象
del += object.FuncB; //增加方法
del += object.FuncC; //增加方法

通過+=符號為委托對象添加更多方法,上例中,del對象不保存了三個方法,在執行del時,這三個方法會被依次調用

注意,在使用+=為委托對象添加新的方法時,實際上是創建了一個新的委托對象(原對象的副本)

移除委托方法

?
1
2
del -= object.FuncB; //移除方法
del -= object.FuncC; //移除方法

通過-=來將委托調用列表中已保存的方法,移除動作是從調用列表的最后一個方法開始匹配,一次只會移除一條匹配的方法,如果調用列表中不存在該方法,則沒有任何效果;如果試圖調用一個空的委托則會發生異常

注意,在使用-=為委托對象移除方法時,實際上是創建一個新的委托對象(原對象的副本)

調用委托

調用委托就像調用方法一樣

示例:MyDel類型參考上面的定義

?
1
2
3
4
5
6
MyDel del = object.FuncA; //創建并初始化委托對象
del += object.FuncB; //增加方法
del += object.FuncC; //增加方法
 
//調用委托
del(55);

參數55會在調用委托對象時依次傳遞給保存的方法

一個完整的委托示例代碼

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CodeForDelegate
{
 class Program
 {
  //定義委托類型
  delegate void PrintFunction(string txt);
 
  //測試類中定義三個方法
  class Test
  {
   public void PrintA(string txt)
   {
    Console.WriteLine("printA:{0}", txt);
   }
 
   public void PrintB(string txt)
   {
    Console.WriteLine("printB:{0}", txt);
   }
 
   public static void PrintC(string txt)
   {
    Console.WriteLine("printC:{0}", txt);
   }
  }
  static void Main(string[] args)
  {
   Test test = new Test();
   PrintFunction pf;
 
   //實例化并創建委托對象
   pf = test.PrintA;
 
   //為委托對象增加方法
   pf += test.PrintB;
   pf += Test.PrintC;
   pf += test.PrintA; //添加一個重復的方法
 
   //通過與null比較,確認委托對象中保存了方法
   if (pf != null)
    pf("Hello");
   else
    Console.WriteLine("pf是個空委托!");
 
   Console.ReadKey();
  }
 }
}

調用帶有返回值的委托

如何委托有返回值,并且調用列表中有一個以上的方法,那么將使用最后一個方法的返回值,之前方法的返回值被忽略

示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CodeForDelegate
{
 class Program
 {
  //定義委托類型
  delegate int DelFunction();
 
  //測試類中定義三個方法
  class Test
  {
   int IntValue = 0;
   
   public int FuncA()
   {
    return IntValue += 1;
   }
 
   public int FuncB()
   {
    return IntValue += 10;
   }
  }
  static void Main(string[] args)
  {
   Test test = new Test();
   DelFunction df;
 
   df = test.FuncA;
   df += test.FuncB;
 
   //最終返回值的是11
   if (df != null)
    Console.WriteLine("返回值:"+df());
   else
    Console.WriteLine("pf是個空委托!");
 
   Console.ReadKey();
  }
 }
}

具有引用參數的委托

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CodeForDelegate
{
 //定義委托類型
 delegate void MyDel(ref int x);
 class Program
 {
 
  static void Add1(ref int x) { x += 1; }
  static void Add2(ref int x) { x += 2; }
 
  static void Main(string[] args)
  {
   Program program = new Program();
 
   MyDel del = Add1;
   del += Add2;
 
   //ref會將x當作引用值傳遞給委托方法
   int x = 5;
   del(ref x);
 
   Console.ReadKey();
  }
 }
}

在調用Add1方法時,x = 5+1,再調用Add2方法時,不是x = 5+2而是x = 6 +2

參考:ref按引用傳遞參數

在方法的參數列表中使用 ref 關鍵字時,它指示參數按引用傳遞,而非按值傳遞。 按引用傳遞的效果是,對所調用方法中參數進行的任何更改都反映在調用方法中。 例如,如果調用方傳遞本地變量表達式或數組元素訪問表達式,所調用方法會替換 ref 參數引用的對象,然后,當該方法返回時,調用方的本地變量或數組元素將開始引用新對象

匿名方法

匿名方法是在初始化委托時內聯聲明的方法

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CodeForDelegate
{
 //定義委托類型
 delegate void MyDel(ref int x);
 class Program
 {
 
  static void Add1(ref int x) { x += 1; }
  static void Add2(ref int x) { x += 2; }
 
  static void Main(string[] args)
  {
   Program program = new Program();
   
   //采用匿名方法形式代替具名方法
   MyDel del = delegate(ref int y) { y += 3; };
   del += Add1;
   del += Add2;
 
   //ref會將x當作引用值傳遞給委托方法
   int x = 5;
   del(ref x);
 
   Console.ReadKey();
  }
 }
}

在聲明委托變量時作為初始化表達式,或在為委托增加事件時使用

語法解析

以關鍵字delegate開頭;后跟小括號提供參數;再后跟{}作為語句塊

delegate (Parameters) {ImplementationCode}

  • 匿名方法不會顯示的聲明返回類型delegate (int x) { return x;}即為返回一個int類型的值
  • 參數的數量、位置、類型、修飾符必須與委托相匹配
  • 可以通過省略圓括號或使圓括號為空來簡化匿名方法的參數列表,前提是參數是不包含out參數,方法體中不使用任何參數

示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CodeForDelegate
{
 //定義委托類型
 delegate void MyDel(ref int x);
 class Program
 {
 
  static void Add1(ref int x) { x += 1; }
  static void Add2(ref int x) { x += 2; }
 
  static void Main(string[] args)
  {
   Program program = new Program();
   
   //采用匿名方法形式代替具名方法
   MyDel del = delegate(ref int y) { y += 3; };
   del += Add1;
   del += Add2;
   
   //匿名方法未使用任何參數,簡化形式
   del += delegate{int z = 10;};
 
   //ref會將x當作引用值傳遞給委托方法
   int x = 5;
   del(ref x);
 
   Console.ReadKey();
  }
 }
}

如果定義一個帶有params形式的參數,在使用匿名方法的時候可以省略params關鍵字以簡化代碼

示例:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace CodeForDelegate
{
 //定義一個帶有params形式參數的委托類型
 delegate void DelFunction(int x, params int[] z);
 class Program
 {
  static void Main(string[] args)
  {
   Program program = new Program();
   
   // 關鍵字params被忽略(省略關鍵字以簡化)
   DelFunction df = delegate(int x, int[] y) { ... };
 
   Console.ReadKey();
  }
 }
}

Lambda表達式

Lambda可以簡化匿名方法,語法形式如下:

(參數) => {語句塊} // => 讀作 gose to

參數中的類型可以省略
如果只有一個參數,圓括號可以省略
如果沒有參數,圓括號不可以省略
語句塊如果只有一行代碼,花括號可以省略

示例:

?
1
2
3
4
MyDel del = delegate(int y) { return y += 3; }; //匿名方法
MyDel del1 = (int y) => {return y += 3;} // Lambda表達式
MyDel del2 = (y) => {return y += 3;} // 省略參數類型
MyDel del3 = y => y += 3; // 省略圓括號和花括號,雖然沒有return,但仍會返回y的值

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對服務器之家的支持。

原文鏈接:https://www.jianshu.com/p/6935eaad5ff8

延伸 · 閱讀

精彩推薦
  • C#C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    C# 實現對PPT文檔加密、解密及重置密碼的操作方法

    這篇文章主要介紹了C# 實現對PPT文檔加密、解密及重置密碼的操作方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下...

    E-iceblue5012022-02-12
  • C#深入解析C#中的交錯數組與隱式類型的數組

    深入解析C#中的交錯數組與隱式類型的數組

    這篇文章主要介紹了深入解析C#中的交錯數組與隱式類型的數組,隱式類型的數組通常與匿名類型以及對象初始值設定項和集合初始值設定項一起使用,需要的...

    C#教程網6172021-11-09
  • C#WPF 自定義雷達圖開發實例教程

    WPF 自定義雷達圖開發實例教程

    這篇文章主要介紹了WPF 自定義雷達圖開發實例教程,本文介紹的非常詳細,具有參考借鑒價值,需要的朋友可以參考下...

    WinterFish13112021-12-06
  • C#C#裁剪,縮放,清晰度,水印處理操作示例

    C#裁剪,縮放,清晰度,水印處理操作示例

    這篇文章主要為大家詳細介紹了C#裁剪,縮放,清晰度,水印處理操作示例,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    吳 劍8332021-12-08
  • C#Unity3D實現虛擬按鈕控制人物移動效果

    Unity3D實現虛擬按鈕控制人物移動效果

    這篇文章主要為大家詳細介紹了Unity3D實現虛擬按鈕控制人物移動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一...

    shenqingyu060520232410972022-03-11
  • C#C#通過KD樹進行距離最近點的查找

    C#通過KD樹進行距離最近點的查找

    這篇文章主要為大家詳細介紹了C#通過KD樹進行距離最近點的查找,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    帆帆帆6112022-01-22
  • C#C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題實例

    這篇文章主要介紹了C#設計模式之Visitor訪問者模式解決長隆歡樂世界問題,簡單描述了訪問者模式的定義并結合具體實例形式分析了C#使用訪問者模式解決長...

    GhostRider9502022-01-21
  • C#C#實現XML文件讀取

    C#實現XML文件讀取

    這篇文章主要為大家詳細介紹了C#實現XML文件讀取的相關代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    Just_for_Myself6702022-02-22
主站蜘蛛池模板: cao逼视频| 亚洲成人伦理 | 亚洲美洲国产日产 | 果冻传媒新在线观看免费 | 国产免费视 | hh99me福利毛片| 国产人妖ts在线视频网 | 欧美整片完整片视频在线 | 日韩一区二区三区四区区区 | 明星ai人脸替换脸忘忧草 | 免费观看欧美性一级 | 出差被灌醉绝伦的上司日本 | 国产欧美久久久精品影院 | 美女被躁爽死 | blacked黑人hd2021| 娇妻被朋友征服中文字幕 | 亚洲精品一区二区久久这里 | 我的男友是消防员在线观看 | 亚洲成在人线久久综合 | 国产成人精品s8sp视频 | 亚洲小视频 | 国产一区二区三区在线观看视频 | 国产亚洲精品高清在线 | 亚洲 无码 制服 日韩 | 精品久久久久久久久久久久久久久 | 午夜国产理论 | 国产乱码免费卡1卡二卡3卡四 | 色播开心网 | 亚洲熟区 | 大逼美女 | 五月色婷婷网在线观看 | 日韩精品一区二区三区老鸭窝 | h日本漫画全彩在线观看 | 脱了白丝校花的内裤猛烈进入 | 国产亚洲精品日韩香蕉网 | 午夜亚洲一区二区福利 | 韩国三级年轻的小婊孑 | www一区二区| 69日本xxxhd | 日韩精品欧美激情国产一区 | 亚洲国产欧美目韩成人综合 |