【C#】委託與事件

來源:互聯網
上載者:User

標籤:des   blog   io   os   使用   ar   for   strong   sp   

一、委託1.概念:用來存放 方法 指標(地址)的容器。

為什麼要有委託?當有的業務代碼總體已經實現,但有部分需要調用者來決定,就可以使用委託的方式,讓調用者把一段代碼以 方法的方式 傳入。

【例子】:

List<Person> list2 = new List<Person>();list2.Add(new Person());list2.Add(new Person());list2.Add(new Person());

 


//平時,我們每次需要遍曆集合的時候都要手寫 迴圈代碼

foreach (Person per in list2){    Console.WriteLine(per.SayHi());}

 


//使用 集合的 ForEach方法,它會幫我們 遍曆 list2裡的元素,但是它不知道每次遍曆要對元素做什麼事情,需要程式員傳入代碼(執行代碼只能放在方法裡,所以這裡需要傳入一個方法)

list2.ForEach(TakeSayHi);

//準備給ForEach的方法

public void TakeSayHi(Person p){      Console.WriteLine(p.SayHi());}

 

【問題】:方法是如何傳遞的呢?

通過 委託類!

2.文法:

2.1簡單實用

2.1.1如何定義委託

public delegate void DGSayHi(Person p);

 

2.1.2如何建立委派物件

//定義方法(其簽名必須與 要添加到的委託 的簽名一致)

public void TakeSayHi(Person p){    Console.WriteLine(p.SayHi());}

 

//建立委派物件(建構函式中傳入方法)DGSayHi dgSayhi = new DGSayHi(TakeSayHi);//2.1.3如何調用委託//1.建立委派物件,傳入 與委託具有相同簽名的方法DGSayHi dgSayhi = new DGSayHi(TakeSayHi);//2.調用委託裡的方法,並為委託裡的方法 傳入參數dgSayhi.Invoke(new Person());

 

 

2.2將方法當參數(本質是把委託當參數,委託裡存放要傳遞的方法)

//定義需要傳遞委託參數的方法:

public void TestDGSayHI(DGSayHi dgSayHI){    Person p = new Person();    dgSayHI.Invoke(p);//通過委託調用隨委託傳進來的方法}

 

 

//測試:DGSayHi dg = new DGSayHi(TakeSayHi);//把方法存在委託中 ,然後 傳遞給 調用方法TestDGSayHI(dg);

 

 

2.3將方法當傳回值(本質是把委託當傳回值,委託裡存放要返回的方法)

public DGSayHi CreateDele(string type) {    switch (type)    {        default:            return new DGSayHi(TakeSayHi);    }}

 

調用:

Person p = new Person();//返回一個 包含了 方法的委派物件DGSayHi dg = CreateDele("p");//通過委託 調用委託裡的方法dg.Invoke(p);

 

 

2.4向委託中存放多個方法(多播委託)

DGSayHi dgSay = new DGSayHi(TakeSayHi);//向委託中 追加 方法(也存在委託中)dgSay += new DGSayHi(TakeSayHiInJp);dgSay += new DGSayHi(TakeSayHiInKr);//調用的時候 會 按照方法添加的順序 依次執行方法 並為 每個方法都傳入相同 的 參數dgSay.Invoke(new Person());

 

 

2.5移除委託中的方法

DGSayHi dgSay = new DGSayHi(TakeSayHi);//向委託中 追加 方法(也存在委託中)dgSay += new DGSayHi(TakeSayHiInJp);dgSay += new DGSayHi(TakeSayHiInKr);//移除委託中的 一個方法dgSay -= new DGSayHi(TakeSayHiInJp);//調用委託中 剩下的兩個方法,並傳入 相同參數dgSay.Invoke(new Person());

 

 

3.文法糖

為了簡化文法,.Net編譯器會認識一些簡單的文法,並在編譯的時候轉成正常文法代碼。因為是在編譯的時候替換,所以不會影響啟動並執行效率。

//3.1建立委託 和 執行委託裡的方法的  文法糖

DGSayHi dgSayHi2 = TakeSayHi;//new DGSayHi(TakeSayHi);dgSayHi2(new Person());//dgSayHi2.Invoke(new Person())

 

 

//3.2直接把方法 作為參數 傳入

TestDGSayHI(TakeSayHi);// TestDGSayHI(new DGSayHi(this.TakeSayHi));

//3.3+= / -=DGSayHi dgSay2 = TakeSayHi;dgSay2 += TakeSayHiInJp;dgSay2 += TakeSayHiInKr;dgSay2 -= TakeSayHiInJp;dgSay2(new Person());

 

編譯後:

DGSayHi dgSay2 = new DGSayHi(this.TakeSayHi);dgSay2 = (DGSayHi) Delegate.Combine(dgSay2, new DGSayHi(this.TakeSayHiInJp));dgSay2 = (DGSayHi) Delegate.Combine(dgSay2, new DGSayHi(this.TakeSayHiInKr));dgSay = (DGSayHi) Delegate.Remove(dgSay, new DGSayHi(this.TakeSayHiInJp));dgSay2.Invoke(new Person());

 

 

注意:方法中不能定義類

private void btnDelSelf_Click(object sender, EventArgs e){//class A{}//delegate void A();//而 委託 就是在一個 類,所以也不能在方法中定義委託}

 

 

4.委託原理

4.1定義委託:

public delegate void DGSayHi(Person p);

 

 

編譯後:會產生一個繼承於 MulticastDelegate 的類!

.class public auto ansi sealed DGSayHi    extends [mscorlib]System.MulticastDelegate{.method public hidebysig newslot virtual instance void Invoke(class 委託事件.Person p) runtime managed......}

 

 

編譯後我們看到了一個繼承關係: 自訂委託類 -> MulticastDelegate ->Delegate

 

4.2委託類 Delegate

DGSayHi dg = new DGSayHi(TestTar);//此處先看成 是 new 了一個 Delegatedg(new Person());

 

 

 

4.2多播委託 MulticastDelegate

 

 

 

 

 

 

5.匿名方法

針對於某些只調用一次的方法,使用匿名方法。

List<Person> list2 = new List<Person>();list2.Add(new Person());list2.Add(new Person());list2.Add(new Person());//匿名方法list2.ForEach(delegate(Person p){    Console.WriteLine(p.SayHi());});

 

 

 

二、事件 Event

為什麼要有事件?

如果所有地方都是用委託,那麼有可能發生這種情況:一個委派物件,已經註冊了若干方法,但某個程式員不知道,直接將委託 設定為 null,清空了所有的方法。

而事件 可以 為我們限制在外部存取某個類裡的 委派物件 的方式,只能在外部通過 +=/-=操作委派物件。

 

1.文法
//1.先定義委託 類public delegate void DGTripleClick();//2.定義事件(在某個類中需要使用委託時,加個event關鍵字)public event DGTripleClick TripleClickEvent;//3.使用事件TripleClickEvent += Mehtod1;TripleClickEvent -= Mehtod1;TripleClickEvent=null;//報錯,事件委託在外部只能在 +=/-=左邊TripleClickEvent();//報錯,事件委託在外部不能直接調用執行

 

 

2.原理

C# 裡的事件 其實是一套類似於 屬性的 文法機制

用來 限制 在某個類的外面 訪問 類裡面的 委託的 方式。

事件會在編譯後 自動的產生一個私人的委託變數,同時產生 addon 和 removeon 兩個公有的 兩個方法用來 +=/-= 操作 這個私人委託變數。

 

 

 

 

 

 

【C#】委託與事件

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.