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

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

詳解C#委托

2019-11-14 15:44:25
字體:
來源:轉載
供稿:網友

   1  委托

    當要把方法傳遞給其他方法時,需要使用委托。有時候某個方法執行的操作并不是針對數據進行的,而是要對另一個方法進行操作。但是編譯的時候,我們不知道第二個方法是什么,這個信息只有在運行時得到,所以需要我們把第二個方法作為參數傳遞給第一個方法。總之,委托就是參數為方法的函數。

    事件——一般是通知代碼發生了什么事件。引發了事件時,運行庫需要知道應該執行哪個方法。這就要把處理事件的方法作為一個參數傳遞給委托。

    1.1  聲明委托

    首先必須定義要使用的委托,對于委托,定義它就是告訴編譯器這種類型的委托表示哪種類型的方法,然后必須創建該委托的一個或者多個實例。編譯器在后臺將創建表示該委托的一個類。語法如下:

    delegate void IntMethodInvoker(int x);

    在這個實例中,定義了一個委托IntMethodInvoker,并指定該委托的每個實例都可以包含一個方法的引用,該方法含有一個int參數,返回void。定義一個委托,必須給出它所表示的方法的簽名和返回類型。定義委托的語法類似方法的定義,但是沒有方法體,定義的前面要加上關鍵字delegate。可以在委托的定義上應用常用的訪問修飾符:public、PRivate、protected等。

    定義委托實際上是定義一個新類。委托實現為派生自基類System.MulticastDelegate的類,System.MulticastDelegate又派生自基類System.Delegate。C#編譯器能識別這個類自動使用其委托語法,我們不需要了解這個類的具體執行情況。

    定義好委托后就可以創建它的一個實例,但創建的委托的實例仍然稱為委托。

    1.2  使用委托

    下面代碼說明如何使用委托,這是在int上調用ToString()方法的一種冗長方式。

  

  private delegate string GetAString();//定義委托,表示的方法不帶參數,返回一個string型的值。    static void Main()    {     int x=40;           GetAString firstStringMethod=new GetAString(x.TOString);//實例化類型為GetAString的委托,并對它進行初始化,//使它引用整形變量x的ToString()方法。在C#中,委托在語法上總是接受一個參數的構造函數,這個參數就是委托引用的方法。//這個方法必須匹配最初定義委托時的簽名。           Console.WriteLine("String is {0}",firstStringMethod());  //使用委托顯示字符串//在任何代碼中,都應該提供委托實例的名稱,這里例子實例名稱為firstStringMethod,后面括號中應該包含調用委托中方法時使用的任何等效參數    } 

 

    在C#編譯時,編譯器會用firstString.Method.Invoke()代替firstStringMethod()。(這是IDE內部實現的,不需要編程者關心,這里只是說明下它的原理。)

    為了減少代碼,只需要委托實例,就可以只傳送地址的名稱,這稱為委托推斷。舉例如下:

    GetAString firstStringMethod =new GetAString(x.ToString);//正常用法

    GetAString firstStringMethod=x.ToString;//委托推斷的用法

    注意:千萬不能輸入x.ToString()。因為加()的方法是返回一個字符串對象,不加括號代表方法地址,委托調用的是方法地址。

    委托的類型是安全的,可以保證被調用的方法簽名正確。

    1.3  Action<T>和Func<T>委托

    以上都是為參數和返回類型定義一個新委托。下面介紹Action<T>委托,泛型Action<T>委托表示引用一個void返回類型方法。Func<T>委托可以調用帶返回類型的方法。Func<out TResult>委托類型可以調用帶返回類型且無參數的方法,Func<int T,out TResult>調用一個帶參數的方法。

    舉例聲明一個該委托類型的數組:

    Func<double ,double>[] Operations=

{

   類名.方法名,類名.方法名

}

    1.4  一個委托的例子:類的冒泡法排序

     class BubbleSorter{  static public void Sort<T>(IList<T> sortArray,Func<T,T,bool>comparison)//接受類型T的泛型方法Sort<T>  {      bool swapped=true;      do       {             swapped=false;             for(int i=0;i<sortArray.Count-1;i++)            {                   if(comparison(sortArray[i+1],sortArray[i]))                    {                        T temp=sortArray[i];                        sortArray[i]=sortArray[i+1];                        sortArray[i+1]=temp;                        swapped=true;                     }                            }                }while(swapped);          }}     class Employee{    public Employee(string name,decimal salary)    {          this.Name=name;this.Salary=salary;     }     public string Name{get;private set;}    public decimal Salary{get;private set;}     public static bool CompareSalary(Employee e1,Employee e2)  {        return e1.Salary<e2.Salary;   }}

 

Main函數調用時:

static void Main(){     Employee[] employees={     new Employee("Buges",2000),     new Employee("Daffy",1000),  new Employee("Foge",2300),  new Employee("Tows",5000),  new Employee("Gay",2100)};BubbleSorter.Sort(employees,Employee.ConpareSalary);//調用類的靜態方法}

 

1.5多播委托

    委托可以包含多個方法,那就是多播委托。為此委托的簽名必須返回void;否則就只能得到委托調用的最后一個方法的結果。多播委托可以識別運算符”+“和”+=“。

    Action<double>operation1=類名1.方法名1;

    Action<double>operation2=類名2.方法名2;

    Action<double>operationS=operation1+operation2;

    多播委托可以用”-“和”-=“以從委托中刪除方法調用。

    多播委托派生自System.MulticastDelegate的類,System.MulticastDelegate又派生自基類System.Delegate。MulticastDelegate的其他成員允許把多個方法調用鏈接成一個列表。

    多播委托要避免依賴于特定順序的代碼。

    如果通過委托調用其中一個方法拋出異常,整個迭代就停止了。為了避免這個問題,Delegate類定義了GetInvocationList()方法,它返回一個Delegate對象數組。先中科院使用這個委托調用與委托直接相關的方法,捕獲異常并繼續下一次迭代。

Action d1= One;d1+=Two;Delegate[] delegates=d1.GetInvocationList();foreach (Action d in delegates){  try  {    d();  }  catch(Exception)  {   Console.WriteLine("Exception caught");  }}

 

1.6  Lambda表達式

    只要有委托參數類型的地方,就可以使用Lambda表達式。簽名使用匿名方法的例子可以改為使用Lambda表達式。Lambda運算符”=>“的左邊列出了需要的參數。Lambda運算符右邊定義了賦予lambda變量的方法的實現代碼。

Func<string,string>oneParam=s=>String.Format("change uppercase{0}",s.ToUpper());Console.WriteLine(oneParam("test"));

 

    1.6.1  參數

Func<double,double,double>twoParamsWithTypes=(double x,double y)=>x*y;Console.WriteLine(twoParamsWithTypes(4,2));

   1.6.2 多行代碼

Func<double,double>square=x=>x*x;

等價于

Func<double,double>square=x=>{   return x*x;}

添加多行語句要有括號和return語句

Func<string,string>lambda=param=>{   param+=mid;   param+=" and this was added to the string.";   return param;}

 

 

    

    

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 中江县| 武威市| 栾川县| 阿拉善左旗| 英德市| 贵溪市| 舞阳县| 河西区| 广东省| 贵港市| 商南县| 清镇市| 古田县| 永善县| 屏东市| 乐业县| 阜阳市| 汉川市| 河东区| 康马县| 金沙县| 龙门县| 深圳市| 安阳市| 吕梁市| 泰州市| 成安县| 德阳市| 太仆寺旗| 东丰县| 基隆市| 永和县| 道孚县| 桃江县| 舟曲县| 临湘市| 开化县| 伽师县| 济阳县| 蒲江县| 阿瓦提县|