C#代理多样性
一、代理
首先我們要弄清代理是個什么東西。別讓一串翻譯過來的概念把大家搞暈了頭。
有的文章把代理稱委托、代表等,其實它們是一個東西,英文表述都是“Delegate”。由于沒有一本權威的書來規范這個概念,所以現在網上對它的稱謂不一。本文我將以“代理”來稱謂Delegate。
代理是什么呢?我認為“代理就是用來定義指向方法的引用”。下面我們就通過類來理解代理。
如:
Ren r = new Ren("車延祿");
上面的代碼,就是使用Ren這個類定義了一個指“車延祿”這個對象實例的一個引用。
也可以這樣理解:用Ren類定義的變量r,指向一個“車延祿”對象的實例。
類所定義的變量指向的是一個對象,代理所定義的變量指向的是個方法,當然這個方法可以是靜態方法也可以是實例方法。對代理引用的調用就是對代理所指向方法的調用。
1.代理聲明的語法:
[public/private] delegate <返回值類型> <代理名稱>(<參數列表>);
[public/private]:訪問修飾符。
delegate:代理聲明關鍵定,相當于類聲明的Class關鍵定
<返回值類型>:代理所指向的方法的返回值類型
<代理名稱>:代理類型的名稱
<參數列表>:代理所的指向的方法的參數列表。
要想使代理對象能夠指向一個方法,那這個方法的要滿足兩個條件
a.方法返回類型要與delegate聲明中的“返回值類型”一致。
b.方法的形參形表要與delegate聲明中的“參數列表”一致。
如:
delegate void MyDelegate(string str,int index);
該代理聲明表示:該代理指向的方法必須是返回空類型,并且擁有兩個參數,第一個是字符串類型,第二個是整型。
2.代理“實例化”:
代理聲明相當于類的定義。有了類的定義后我們要還需生成這個類的對象;同樣有了代理的聲明我們還需要“實例化”代理
如:MyDelegate md = new MyDelegate(Show);
這里的md就是代理變量。在代理的“實例化”的時候必須在構造函數中傳入一個方法名。這個方法名就是該代理指向的方法,當然該方法的返回值類型與參數類型一定要與代理的聲明一致。
Show方法定義如下:
public static void Show(string str, int index)
{
Console.WriteLine("Show"+str+index.ToString());
}
3.代理的調用:
md("hello world",22);
此時調用的就是md這個代理變量所指向的Show方法。
4.例子:
delegate void MyDelegate(string str,int index);??? //聲明代理
class Test
{
public static void Show(string str, int index)???? //聲明方法
{
Console.WriteLine("Show"+str+index.ToString());
}
public static void Main(string[] args)
{
MyDelegate md = new MyDelegate(Show);?//1.實例化代理,傳入方法
md("hello world",22);????????????????????????????????????//2.傳入參數
}
}
5.代理的應用:
代理的主要應用就是在DotNet中的事件處理,所以要想研究事件我們必須要理解代理的概念。有的文章使用代理進行冒泡排序,我感覺這沒必要,因為不用代理我也可以排序,更況且在C#語法中也不需要我們手動編寫冒泡排序代碼。
關于代理,大家要理解代理是個什么東西,并且能夠寫一個簡單的代理示例就可以了。
二、多播代理
上面我們講的代理是一個代理對象指向一個方法,在調用該代理對象的時候就會調用它所指向的方法。多播代理就是為一個代理掛接上多個方法,當執行該代理的時候就會依次執行該代理上掛接的方法。
1.多播代理的聲明與上面講得基本上一樣:
[public/private] delegate void <代理名稱>(<參數列表>);
只有一點不一樣的就是,多播代理所指向的方法應當是void類型。
2.多播代理“實例化”
多播代理“實例化”與上面講得一樣,在此不多說了。
如:MyDelegate md = new MyDelegate(Show);
3.多播代理掛接多個方法。
多播代理可以使用 += 運算符掛接多個方法,也可以使用 -= 運算符從掛接列表中刪除相應的掛接方法。
如:
delegate void MyDelegate(string str,int index);
class Test
{
public static void Show(string str, int index)
{
Console.WriteLine("Show"+str+index.ToString());
}
public static void TestInt(string str, int index)
{
Console.WriteLine("Testint");
}
public static void Main2(string[] args)
{
MyDelegate md = new MyDelegate(Show);? //傳入方法
md += new MyDelegate(TestInt);?????????????????? //傳入另一個方法
md("hello world",22);
}
}
在上面這個例子當中有兩個方法(Show和TestInt)符合MyDelegate代理的簽名,如果要把這兩個方法掛接到我們一個代理變量上去的話,就得用 += 運算符了。
MyDelegate md = new MyDelegate(Show);
md += new MyDelegate(TestInt);
這里的md代理變量上先掛接了Show方法,再掛接TestInt方法。當執行md("hello world",22)的時候會先調用Show方法,再調用TestInt方法。
事件本身就是一種多播代理
??? 三、事件:????1.用執行事件傳入參數???? 2.用注冊事件傳入方法
C#中的事件就是代理的一個變量。它和屬性、方法一樣,都是類的成員。只不過事件是指向一個方法,當事件被觸發時,就會執行對象的相關方法。
事件的這種對方法的引用并不是寫死在代碼里面的,而是可以進行更改的。辟如:我們在DotNet中按鈕的OnClick事件,它可以指向符合OnClick事件簽名的任何一個方法。
1.事件的定義使用event關鍵字:
public event CryHandler DuckCryEvent;
其中的CryHandler是一個delegate。從上面的代碼我們可以看出來:事件就是一個代理類型的變量。
private delegate void CryHandler();
2.指定事件處理程序:
指定事件處理程序就是為事件掛接方法的過程。
DuckCryEvent +=new CryHandler(Cry);???//注冊事件,傳入方法
public void Cry()
{
Console.WriteLine("我是一只小鴨,呀依呀依呀....");
}
3.執行事件
執行事件就是調用事件所指向方法的過程。一般對事的執行代碼寫在相應的方法或屬性中,如果方法或屬性被調用時就觸發事件。
public void BeShaked()
{
DuckCryEvent();
}
4.完整的例子:
//事件用到的代理,以般以×××Handler的格式進行命名
private delegate void CryHandler();?????????????//無參代理
//玩具小鴨的類
class Duck
{
??//定義小鴨的唱歌事件
public event CryHandler DuckCryEvent;
public Duck()
{
??//把小鴨唱歌的事件掛接到Cry方法上
DuckCryEvent +=new CryHandler(Cry);?//注冊事件,傳入方法
}
//小鴨唱歌事件對應的處理方法
public void Cry()
{
Console.WriteLine("我是一只小鴨,呀呀呀....");
}
//小鴨被搖動
public void BeShaked()?//執行方法,引發cry事件
{
DuckCryEvent();??????????????????????????????????//執行事件,傳入參數
}
}
class Class2
{
public static void Main3(string[] args)
{
??//買一只小鴨
Duck d = new Duck();
//搖一搖小鴨,它就會調觸發小鴨的Cry事件,小鴨就會唱歌
d.BeShaked();
}
}
?? 四、注意事項
C#中的delegate和C++中的函數指針基本是一回事,C#正是以delegate的形式實現了函數指針。不同的地方在于C#中delegate是類型安全的并且完全面向對象的。
Delegate?與C++相比優點:
A、函數指針只能指向靜態函數,而delegate既可以指向靜態函數也可以指向非靜態成員函數。
B、與函數指針相比,delegate?是面向對象、類型安全、可靠的受控對象,runtime?能夠保證delegate?指向一個有效的方法,不須擔心delegate指向無效地址或是越界地址。
?
要理解Delegate,首先,你要明白,它是一個類,他和Class是一個級別的概念,不同在于Class的定義包含字段和方法,而delegate只包含方法的細節。Delegate?類能夠擁有一個簽名(signature),并且它只能持有與他的簽名相匹配的方法的引用。
(1)在C#中,所有的代理都是從System.Delegate類派生的(delegate是System.Delegate的別名)。
(2)代理隱含具有sealed屬性,即不能用來派生新的類型。
(3)代理最大的作用就是為類的事件綁定事件處理程序。
(4)在通過代理調用函數前,必須先檢查代理是否為空(null),若非空,才能調用函數。
(5)在代理實例中可以封裝靜態的方法也可以封裝實例方法。
(6)在創建代理實例時,需要傳遞將要映射的方法或其他代理實例以指明代理將要封裝的函數原型(.NET中稱為方法簽名:signature)。注意,如果映射的是靜態方法,傳遞的參數應該是類名.方法名,如果映射的是實例方法,傳遞的參數應該是實例名.方法名。
(7)只有當兩個代理實例所映射的方法以及該方法所屬的對象都相同時,才認為它們是想等的(從函數地址考慮)。
(8)多個代理實例可以形成一個代理鏈,System.Delegate中定義了用來維護代理鏈的靜態方法Combion,Remove,分別向代理鏈中添加代理實例和刪除代理實例。
(9)代理三步曲:
?????????? a.聲明一個delegate對象,它應當與你想要傳遞的方法具有相同的參數和返回值類型:?? delegate?int?MyDelegate();
???????? ? b.創建delegate對象,并將你想要傳遞的函數作為參數傳入:
??????????????????? MyDelegate?d?=?new?MyDelegate(MyClass.MyMethod);
????????? c.在要實現異步調用的地方,通過上一步創建的對象來調用方法。using?System;
?????????????????????? int?ret?=?d();?
????????? 五、托管函數
?????????????????? 1、什么是托管函數?
?????????????????????????? ?托管函數是一個對類里面的某個函數的一個引用。它子并沒有具體的函數定義,只是指向某個函數實現。
????????????????? 2、托管函數有什么作用?
?????????????????????由于托管函數是對類里面某個函數的一個引用.所以我們不必知道這個函數的具體名字是什么,而只需要調用托管函數,讓托管函數去調用相應的函數就可以了.?一個例子:?一個公司,一個領導,一個領導秘書,三個員工分別管理市場,策劃和生產.這里秘書就相當與一個托管函數,?領導要下達什么命令(獲得市場信息,生產什么產品),只需要對秘書說給我一份市場報告或者我們不生產原子彈轉向生產氫彈.然后再由秘書根據領導的命令選擇的去找哪個員工,再把員工獲得的信息返回給領導.?這里面三個員工對于領導是透明的,領導并不知道自己下達的命令具體是由誰執行的.
示例:?//給秘書下達命令執行
public?void?ExecuteCommand(string?command)
{??switch(秘書根據命令判斷是要給誰執行的)
{??//?這里的實現類似于某種設計模式
case?調研市場的人:
Doit=new?Do(new?MarketMan().GetMarketInfo);Break;
Case?生長產品的人:
Doit=new?Do(new?ProductMan().ProduceProduct);Break;
?????Default:?Break;
?}
}
轉載于:https://www.cnblogs.com/w-wfy/p/7227735.html
總結
- 上一篇: $.post()提交了数据,return
- 下一篇: AJAX扩展-POST传递参数并跳转页面