日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详解委托

發(fā)布時間:2025/3/20 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解委托 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

委托和事件在 .Net Framework 中的應用非常廣泛,然而,較好地理解委托和事件對很多接觸C#時間不長的人來說并不容易。它們就像是一道檻兒,過了這個檻的人,覺得真是太容易了,而沒有過去的人每次見到委托和事件就覺得心里堵得慌,渾身不自在。本章將由淺入深地講述什么是委托、為什么要使用委托、事件的由來等。

7.1 理解委托

7.1.1 將方法作為方法的參數(shù)

先不管這個標題是如何的繞口,也不管委托究竟是個什么東西,來看下面這兩個最簡單的方法,它們不過是在屏幕上輸出一句問候的話語:

public void GreetPeople(string name)

{

??? //做某些額外的事情,比如初始化之類,此處略

??? EnglishGreeting(name);

}

public void EnglishGreeting(string name)

{

??? Console.WriteLine(string.Format("Hello,{0}", name));

}

暫且不管這兩個方法有沒有什么實際意義。GreetPeople 用于向某人問好,當傳遞代表某人姓名的name 參數(shù)值如“歐旭”時,在這個方法中,將調用EnglishGreeting方法,再次傳遞name 參數(shù)值進入EnglishGreeting方法中,然后輸出 “Hello,歐旭”。

現(xiàn)在假設這個程序需要進行全球化,輸出的問候語需要中文形式,怎么辦呢?解決辦法是再加個中文版的問候方法:

public void ChineseGreeting(string name)

{

??? Console.WriteLine(string.Format("您好,{0}", name));

}

此時,GreetPeople方法也需要改一改了,用來判斷到底用哪個版本的Greeting 問候方法合適。在進行這個之前,我們最好再定義一個枚舉作為判斷的依據(jù):

public enum Language

{

??? English, Chinese

}

GreetPeople方法修改如下:

public void GreetPeople(string name,Language language)

{

??? //做某些額外的事情,比如初始化之類,此處略

??? switch (language)

??? {

??????? case Language.Chinese:

??????????? ChineseGreeting(name); break;

??????? case Language.English:

??????????? EnglishGreeting(name); break;

??? }

}

以上方法盡管解決了問題,但這個解決方案的可擴展性很差,如果日后需要再添加韓文版、日文版,就不得不反復修改枚舉和GreetPeople()方法,以適應新的需求。

在考慮新的解決方案之前,先看看 GreetPeople的方法簽名:

public void GreetPeople(string name,Language language)

僅看 string name,在這里,string 是參數(shù)類型,name 是參數(shù)變量,當賦給name字符串“歐旭”時,它就代表“歐旭”這個值;當賦給它“ouxu”時,它又代表著“ouxu”這個值。然后,我們可以在方法體內對這個name 進行其他操作。

如果再仔細想想,假如GreetPeople()方法可以接受一個參數(shù)變量,這個變量可以代表另一個方法,當我們給這個變量賦值EnglishGreeting的時候,它代表著 EnglsihGreeting() 這個方法;當我們給它賦值ChineseGreeting的時候,它又代表著ChineseGreeting()方法。我們將這個參數(shù)變量命名為 MakeGreeting,那么可以如同給name 賦值時一樣,在調用 GreetPeople()方法的時候,給這個MakeGreeting參數(shù)也賦上值ChineseGreeting 或者EnglsihGreeting 等。然后,我們在方法體內,也可以像使用別的參數(shù)一樣使用MakeGreeting。但是,由于MakeGreeting 代表著一個方法,它的使用方式應該和它被賦的方法(比如ChineseGreeting)是一樣的,比如:

MakeGreeting(name);

再有了以上思路以后,我們現(xiàn)在就來改改GreetPeople()方法,那么它應該是如下樣子:

public void GreetPeople(string name, *** MakeGreeting)

注意到***,這個位置通常放置的應該是參數(shù)的類型,但到目前為止,我們僅僅是想到應該有個可以代表方法的參數(shù),并按這個思路去改寫GreetPeople方法,現(xiàn)在就出現(xiàn)了一個大問題:這個代表著方法的MakeGreeting參數(shù)應該是什么類型的?

注意:這里已不再需要枚舉了,因為在給MakeGreeting賦值的時候動態(tài)地決定使用哪個方法,是ChineseGreeting 還是 EnglishGreeting,而在這個兩個方法內部,已經對使用“Hello”還是“你好”作了區(qū)分。

到此,要解決GreetPeople(string name, *** MakeGreeting)方法中的***參數(shù)類型問題,就必須使用委托機制。但講述委托之前,我們再看看MakeGreeting 參數(shù)所能代表的 ChineseGreeting()和EnglishGreeting()方法的簽名:

public void EnglishGreeting(string name)

public void ChineseGreeting(string name)

如同name 可以接受string 類型的“true”和“1”,但不能接受bool 類型的true 和int 類型的1 一樣。MakeGreeting 的參數(shù)類型定義應該能夠確定MakeGreeting可以代表的方法種類,再進一步講,就是MakeGreeting可以代表的方法的參數(shù)類型和返回類型。

于是,委托出現(xiàn)了:它定義了MakeGreeting 參數(shù)所能代表的方法的種類,也就是MakeGreeting參數(shù)的類型。

public delegate void GreetingDelegate(string name);

可以與上面EnglishGreeting()方法的簽名對比一下,除了加入了delegate 關鍵字以外,其余的完全一樣?,F(xiàn)在,讓我們再次改動GreetPeople()方法,如下所示:

public void GreetPeople(string name, GreetingDelegate MakeGreeting)

{

??? //做某些額外的事情,比如初始化之類,此處略

??? MakeGreeting(name);

}

如你所見,委托GreetingDelegate 出現(xiàn)的位置與 string 相同,string 是一個類型,那么GreetingDelegate 應該也是一個類型,或者叫類(Class)。但是委托的聲明方式和類卻完全不同,實際上,委托在編譯的時候確實會編譯成類。因為delegate 是一個類,所以在任何可以聲明類的地方都可以聲明委托。這個范例的完整代碼如下:

using System;

?

namespace 委托和事件

{

??? public delegate void GreetingDelegate(string name);//定義委托

??? public? class MyClass

??? {

??????? public static void Main()

??????? {

??????????? GreetPeople("歐旭", EnglishGreeting);

??????????? GreetPeople("ouxu", ChineseGreeting);

??????? }

??????? public void GreetPeople(string name, GreetingDelegate MakeGreeting)

??????? {

??????????? //做某些額外的事情,比如初始化之類,此處略

??????????? MakeGreeting(name);

??????? }

??????? public void EnglishGreeting(string name)

??????? {

??????????? Console.WriteLine(string.Format("Hello,{0}", name));

??????? }

??????? public void ChineseGreeting(string name)

??????? {

??????????? Console.WriteLine(string.Format("您好,{0}", name));

??????? }

??? }

}

輸出為:

Hello,歐旭

你好,ouxu

到此,可以對委托作一個總結:

委托是一種類型,它定義了能代表一類方法的類型,使得可以將該類方法當作另一個方法的參數(shù)來進行傳遞,這種將方法動態(tài)地賦給參數(shù)的做法,可以避免在程序中大量使用If‐Else(Switch)語句,同時使得程序具有更好的可擴展性。

7.1.2 將方法綁定到委托

?????? 在上面的例子中,我們不一定要直接在GreetPeople()方法中給 name 參數(shù)賦值,可以像這樣使用變量:

public static void Main()

{

??? string name1 ,name2;

??? name1 = "歐旭";

??? name2 = "ouxu";

??? GreetPeople(name1, EnglishGreeting);

??? GreetPeople(name2, ChineseGreeting);

}

而既然委托GreetingDelegate 和類型string的地位一樣,都是定義了一種參數(shù)類型,那么,我們也可以如下的方式使用委托:

public static void Main()

{

??? string name1,name2;

??? GreetingDelegate delegate1, delegate2;

??? name1 = "歐旭";

??? name2 = "ouxu";

??? delegate1=EnglishGreeting;

??? delegate2=ChineseGreeting;

??? GreetPeople(name1,delegate1);

??? GreetPeople(name2,delegate2);

}

以上程序運行正常。但是要注意,委托不同于string的一個特性:可以將多個方法賦給同一個委托,或者叫將多個方法綁定到同一個委托,當調用這個委托的時候,將依次調用其所綁定的方法。在這個例子中,語法如下:

public static void Main()

{

??? GreetingDelegate delegate1;

??? delegate1 = EnglishGreeting; // 先給委托類型的變量賦值

??? delegate1 += ChineseGreeting; // 給此委托變量再綁定一個方法

??? GreetPeople("ouxu", delegate1);

}

輸出為:

Hello,ouxu
你好,ouxu

實際上,我們也可以繞過GreetPeople 方法,通過委托來直接調用EnglishGreeting 和ChineseGreeting:

public static void Main()

{

??? GreetingDelegate delegate1;

??? delegate1 = EnglishGreeting;

??? delegate1 += ChineseGreeting;

??? //GreetPeople("ouxu", delegate1);

??? delegate1("ouxu");

}

注意這里,第一次用的“=”,是賦值的語法;第二次,用的是“+=”,是綁定的語法。如果第一次就使用“+=”,將出現(xiàn)“使用了未賦值的局部變量”的編譯錯誤。

我們也可以使用下面的代碼來這樣簡化這一過程:

GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);

delegate1 += ChineseGreeting;

既然可以給委托綁定一個方法,那么也應該有辦法取消方法的綁定,很容易想到,這個語法是“‐=”:

public static void Main()

{

??? GreetingDelegate delegate1 = new GreetingDelegate(EnglishGreeting);

??? delegate1 += ChineseGreeting;

??? GreetPeople("ouxu", delegate1);

??? Console.WriteLine("----------------------------------------------------------------------------------------");

??? delegate1 -= EnglishGreeting;

??? GreetPeople("ouxu", delegate1);

}

輸出為:

Hello,ouxu
你好,ouxu

----------------------------------------------------------------------------------------

你好,ouxu

讓我們再次對委托作個總結:使用委托可以將多個方法綁定到同一個委托變量,當調用此變量時(這里用“調用”這個詞,是因為此變量指向一個方法),可以依次調用所有綁定的方法。如果把多個方法綁定到同一個委托變量上,這種委托稱為多播委托。在多播委托中,委托定義返回值通常為void,這是因為可以給委托變量綁定多個方法,如果定義了返回值,那么多個方法都會返回值,結果就是后面一個返回的方法值將前面的返回值覆蓋掉,因此,實際上只能獲得最后一個方法調用的返回值,多播委托中定義非void返回值沒有多大意義。

7.1.3 匿名方法

在之前的委托學習中,要想使委托工作,方法必須已經存在,即之前的EnglishGreeting()和ChineseGreeting()是事先定義的。但使用委托還有另外一種方式:即通過匿名方法。匿名方法是用作委托參數(shù)的一個代碼塊。

用匿名方法定義委托的語法與前面的定義并沒有區(qū)別。但在實例化委托時,就有區(qū)別了。下面是一個非常簡單的應用程序,說明了如何使用匿名方法:

namespace 委托和事件

{

??? public delegate void GreetingDelegate(string name);//定義委托

?

??? public class MyClass

??? {

??????? public static void Main()

??????? {

??? ????????GreetingDelegate delegate1 = delegate(string name)

??????????? {

??????????????? Console.WriteLine(string.Format("您好,{0}", name));

??????????? };

??????????? delegate1("ouxu");

??????? }?????

??? }

}

在以上程序中,在定義委托變量delegate1時,不是傳送已知的方法名,而是使用一個簡單的代碼塊:它前面是關鍵字delegate,后面是一個參數(shù):

delegate(string name)

{

?? Console.WriteLine(string.Format("您好,{0}", name));

};

匿名方法的優(yōu)點是減少了要編寫的代碼,方法僅在使用委托時才定義,這有助于降低代碼的復雜性。使用匿名方法時,雖然我們沒有指定固定的方法名,但編譯器在編譯此段代碼時仍定義了一個帶有方法名的方法,但我們不需要知道這個方法。

轉載于:https://www.cnblogs.com/gyouxu/archive/2013/04/17/3027382.html

總結

以上是生活随笔為你收集整理的详解委托的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。