国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

親們,委托你們是否已忘記

2019-11-17 02:42:53
字體:
來源:轉載
供稿:網友

親們,委托你們是否已忘記

委托和事件是.Net 框架的重要組成部分,在GUI程序開發中,大量使用了事件處理,但是親們,對于委托,我們是否還記得曾經在書上看到的詳細內容。委托的使用注意事項是什么?我們會使用委托和事件,但是我們不了解事件背后的原理,親們,我們忘記委托了嗎?反正我是忘記了。

委托是方法調用的指針,也稱為函數指針,是一種特殊的對象類型,包含的是方法的地址。注意是地址,在.Net 中,委托不同于c++中的函數指針,在C#中 委托是類型安全的操作,這意味著什么呢?這意味著我們定義的方法簽名必須和委托的定義類型以及返回值一致,否則會出現編譯錯誤的提示信息。

如何定義一個委托:

delegate int AddDelegate(int x,int y); 委托的定義和類的定義一致,在任何可以定義類的地方都可以定義委托,另外,委托 的實現是繼承自MulticastDelegate 類的,也就是說定義一個委托,基本上等價于定義一個新類。委托類似于方法的定義,但是沒有方法體,只有方法簽名,另外在方法簽名的前面添加了delegate關鍵字。

定義一個簡單的委托實例:

 1   class PRogram 2     { 3         static void Main(string[] args) 4         { 5             Test t = new Test(); 6             t.Execute(3, 5); 7             Console.Read(); 8         } 9     }10 11     public class Test12     {13         /// <summary>14         /// 在類的內部定義了一個委托15         /// </summary>16         /// <param name="x"></param>17         /// <param name="y"></param>18         /// <returns></returns>19         delegate int AddDelegate(int x, int y);20         /// <summary>21         /// 實例方法Add1 和委托具有相同的方法簽名22         /// </summary>23         /// <param name="x"></param>24         /// <param name="y"></param>25         /// <returns></returns>26         public int Add1(int x, int y)27         {28             Console.WriteLine("Add1計算得到的值為" + (x + y));29             return x + y;30         }31         /// <summary>32         /// 靜態方法Add2 和委托具有相同的方法簽名33         /// </summary>34         /// <param name="x"></param>35         /// <param name="y"></param>36         /// <returns></returns>37         public static int Add2(int x, int y)38         {39             Console.WriteLine("Add2計算得到的值為" + (x + y * 2));40             return x + y * 2;41         }42 43         public void Execute(int x, int y)44         {45             AddDelegate addDelegate = new AddDelegate(Add1);46             addDelegate += Add2;   //通過+=  多播委托 ,表示一個委托實例具有多個方法,多播委托不能保證方法的執行順序。47             addDelegate(x, y);48         }49         /// <summary>50         /// 多播委托在其中一個調用方法出現異常時會停止迭代,我們優先采用下面方法,即逐個的調用 方法列表執行,可以避免由于某個調用方法出現異常,導致其他調用方法無法執行的問題51         /// </summary>52         /// <param name="x"></param>53         /// <param name="y"></param>54         public void Execute3(int x, int y)55         {56             AddDelegate addDelegate = new AddDelegate(Add1);57             addDelegate += Add2;   //通過+=  多播委托 ,表示一個委托實例具有多個方法,多播委托不能保證方法的執行順序。58             if (addDelegate != null)59             {60                  Delegate[] addArr = addDelegate.GetInvocationList();//獲取多播委托的調用列表61                  if (addArr != null)62                  {63                      foreach (var item in addArr)64                      {65                          ((AddDelegate)item)(x, y);66                      }67                  }68             }69         }70         public void Execute1(int x, int y)71         {72             AddDelegate addDelegate = Add1;//直接為委托實例賦值方法簽名   稱為委托推斷   .Net 編譯器會識別委托簽名73             addDelegate += Add2;74             addDelegate(x, y);75         }76     }

實例總結:

  1. addDelegate =Add1 這種為委托實例賦值的方式稱為 委托推斷,是由.Net 編譯器自動推斷方法簽名是否符合委托。
  2. 委托可以通過+= 來實現一個委托實例具有多個調用方法執行,請注意,多播委托的執行不能保證順序,即不能保證方法注冊的次序和調用次序一致。2.多播委托在執行過程中,如果某個調用方法出現異常,則整個多播委托的調用方法列表都會停止執行,我們可以采用Execute3 展示的那樣,逐個手動執行調用方法列表,避免由于某個調用方法出現異常,導致其他調用方法不會執行的問題。
  3. 委托實例的方法即可以是實例方法,又可以是靜態方法,只要保證方法簽名一致就可以正常的調用。
  4. 委托可以作為參數傳遞,下面我們會展示一個通過將委托作為實例,來實現排序的功能。
  5. 委托可以具有訪問修飾符public、protected以及private等。
  6. 可以通過委托的簡便方式,匿名方法來直接定義一個方法到委托實例,.Net 編譯器會幫助我們生成一個隨機的方法名稱,只是我們不需要。
  7. lambda 也可以應用到委托中,通過lambda表達式生成的是匿名方法,或者說是匿名委托。

我們來定義一個將委托作為參數傳遞,實現排序的功能。目前我們的需求是創建一個通用類庫,其中有一個可以將數組中的內容按升序排列,但是數組的數據類型我們可以自定義,也就是說,我們不能指定數組的數據類型為某一種具體類型,可以為int、double ,也可以為類。

 1  class Program 2     { 3         static void Main(string[] args) 4         { 5             //Test t = new Test(); 6             //t.Execute(3, 5); 7             List<string> listInt = new List<string>(); 8              9             List<Employee> listEmployee = new List<Employee>();10             for (int i = 10; i >= 0; i--)11             {12                 listInt.Add(i.ToString());13                 Employee employee = new Employee()14                 {15                     Name = i.ToString(),16                     Salary = i17                 };18                 listEmployee.Add(employee);19             }20             Test1 test1 = new Test1();21             Employee[] arrEmployee = listEmployee.ToArray();22             test1.Sort(arrEmployee, test1.CompareEmployee);23 24             foreach (var item in arrEmployee)25             {26                 Console.WriteLine(item.Salary);27             }28            29             string[]arrInt=listInt.ToArray();30             test1.Sort(arrInt, test1.CompareInt);31             foreach (var item in arrInt)32             {33                 Console.WriteLine(item);34             }35 36 37 38             Console.Read();39         }40     }41     public class Test142     {43 44         /// <summary>45         /// 委托 比較兩個值的大小 x>y 返回true46         /// </summary>47         /// <param name="x"></param>48         /// <param name="y"></param>49         /// <returns></returns>50       public  delegate bool Compare(object x, object y);51 52         public void Sort(object[] arrObj, Compare compare)53         {54             for (int i = 0; i < arrObj.Length; i++)55             {56                 for (int j = i+1; j < arrObj.Length; j++)57                 {58                     if (compare(arrObj[i], arrObj[j]))59                     {60                         object temp = arrObj[i];61                         arrObj[i] = arrObj[j];62                         arrObj[j] = temp;63                     }64                 }65             }66         }67 68 69         public bool CompareEmployee(object em1, object em2)70         {71             if (em1 != null && em2 != null)72             {73                 return ((Employee)em1).Salary > ((Employee)em2).Salary;74             }75             return false;76         }77 78         public bool CompareInt(object x, object y)79         {80             return Convert.ToInt32(x) > Convert.ToInt32(y);81         }82 83     }84     /// <summary>85     /// 員工類86     /// </summary>87     public class Employee88     {89         /// <summary>90         /// 員工姓名91         /// </summary>92         public string Name { get; set; }93         /// <summary>94         /// 員工工資95         /// </summary>96         public int Salary { get; set; }97     }

總結:

  1. 將委托作為參數進行傳遞,實現了泛型委托可以實現的功能。
  2. 可以在子類實現具體的功能,然后傳遞到對應的方法執行,可以有效的實現可擴展性,同時避免對其他功能的干擾。

委托作為事件的基礎,本身 只具有簡單的一些概念,但是我覺得要真正的在實際項目中可以靈活的使用,還是需要深入思考,做個好夢


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 新竹市| 巴马| 柳河县| 柯坪县| 科技| 马边| 石泉县| 桃江县| 岚皋县| 合川市| 沧源| 邳州市| 二连浩特市| 黄石市| 宕昌县| 略阳县| 绥德县| 彭泽县| 平利县| 阳春市| 尚志市| 长白| 铜梁县| 甘泉县| 巴林左旗| 林西县| 永丰县| 嘉鱼县| 民县| 涪陵区| 驻马店市| 荆门市| 宝鸡市| 海兴县| 巩留县| 桂阳县| 天全县| 怀安县| 三穗县| 南投县| 盘锦市|