1. 程式人生 > >委託與事件簡介

委託與事件簡介

轉載於:點選開啟連結 (http://www.cnblogs.com/wangjiming/p/8300103.html)

本篇文章主要採用理論和程式碼例項相結合方式來論述委託和事件,涉及到一些邊界技術,如軟體架構的OCP原則(開-閉原則),

軟體架構解耦,設計模式(Sender-Order)和事件驅動模型,有一定難度和深度,不適合初級者。

第一部份   委託

關於委託內容,主要圍繞下圖來論述。

 一   委託是什麼(what)

(一)委託產生的背景之一

1.我們先來假設這樣一個情景需求:

   設計一個系統,使其滿足如下條件:

   (1)當前,只有中國人和英國人使用該系統;

   (2)向系統輸入使用者名稱和相應的語言,將產生相應語言的問候語;

      

  (3)後期,可能會有其他國家語言加入該系統(系統變化的部分) ;

 2.技術方案實現

關於技術方案實現,我們可以採用下圖中的三種方式之一。

為了更好地敘述委託,我們分別實現三種技術方案,並找出它們的關係。

 2.1 一般實現

Code(控制檯程式)

 View Code

 Result

分析

 

2.2用介面實現

如上,我們分析了方案一中的問題,為了更好地解決方案一存在的問題,我們採用面向介面程式設計的形式來實現。

2.2.1  什麼是面向介面程式設計?

面向介面程式設計,主要是解決軟體架構設計中“動靜問題”,即封裝不變(靜),剝離變化(抽出變化)。

 Code:

 View Code

result

分析:

(1)如上,我們將變化因子"語言"剝離出來,形成介面,以後只要每增加一個語言,只需實現介面即可,滿足了OCP原則,基本解決了方案一中存在的問題;

(2)如上程式碼只是為了演示面向介面程式設計這個功能,並不完善,感興趣的讀者,可自行完善(如將語言定義為列舉型別等);

方案二中的程式碼,細心的讀者會發現,Main方法中new了三個物件,假若以後系統有300門語言,那豈不New 300個類,這樣的話,也不利於程式碼維護呀,怎麼解決這個問題呢?(提示一下,採用設計模式抽象工廠即可解決該問題)

2.3 用委託實現

在這裡,沒接觸過委託的讀者,先跳過這部分,往下讀,看完(三)怎樣使用委託(How to use)後,再來看本部分。

 Code

 View Code

 Result

 2.3 分析上述三種實現方案的關係

通過上訴三種方式的比較,我們容易得出委託的如下結論:

(1)抽象方法,遮蔽方法細節,呼叫只需傳遞方法名字即可;

(2)能夠實現程式的解耦,鬆耦合(在方案一中,GetGreetingContens方法體內new了GreetToUsers物件,強耦合)

(3)委託一般扮演中間者的角色,這功能在委託事件中體現非常明顯(第二部分 事件 將詳細論述)

如我們在租房子時,可以直接找房東(技術實現的一般方法,強耦合,讓租房者和房東直接聯絡),也可找中介(技術實現的委託,鬆耦合,租房者通過中介來與房東聯絡)

 

2.4 委託背景概述

委託的重要產生背景,就是事件驅動模型(關於什麼是事件和事件驅動,在本文第二部份 事件 論述)。

(二) 委託定義

 用delegate關鍵字定義委託(注意,委託是沒有方法體的,類似接口裡面的方法),在定義委託前,必須明確兩個問題:

1.委託將要繫結的方法;

2.委託的形參型別,形參個數和委託的返回值必須與將要繫結的方法的形參型別,形參個數和返回值一致;

(三)相關概念

委託涉及的相關概念有函式指標,型別安全性、事件、Lambda表示式等

1.函式指標:在C++中,指標的一個類別,主要指向函式(變數指標,主要指向變數地址),可以把C#中的委託理解為函式指標;

2.型別安全性:在C++中,我們都知道指標是型別不安全的(返回值,返回型別和什麼時候返回,這些都是未知的),而委託是型別安全的;

3.事件:可以把事件理解為委託的一種特例(在本文第二部份 事件 論述)

4.Lambda表示式:委託與Lambd表示式相結合,實現高效程式設計,與Jquery的“較少程式碼做更多的事”類似,委託與Lambda,Linq相結合,使較短程式碼就能實現比較複雜的功能(在本篇文章中不講解Lambda與Lambda樹,將在後續文章中講解)

(四)委託組成

大致分為兩部分:宣告委託和註冊方法(也叫繫結方法)

1.宣告委託

用delegate宣告;

2.繫結方法

繫結具體方法,傳遞方法名稱;

(五) 委託種類

委託種類,一般分為多播委託和單播委託

1.單播委託:繫結單個方法

2.繫結多個方法

(六) 委託操作

1.繫結方法

2.解綁方法

二  委託能解決什麼問題(Can do)

1.避免核心方法中存在大量的if....else....語句(或swich開關語句);

2.滿足程式設計的OCP原則;

3.使程式具有擴充套件性;

4.繫結事件;

5.結合Lambda表示式,簡化程式碼,高效程式設計;

6.實現程式的鬆耦合(解耦),這個在事件(event)中體現比較明顯;

三  怎麼使用委託(How to use)(本篇文章不談匿名委託,匿名委託具體內容,將在Lambda章節講解)

(一)委託的基本構成

通常地,使用委託的步驟與使用類的步驟是一樣的。大致分為兩步:定義委託和繫結方法(傳遞方法)

1.定義委託

用delegate關鍵字定義委託(注意,委託是沒有方法體的,類似接口裡面的方法),在定義委託前,必須明確兩個問題:

(1).委託將要繫結的方法;

(2).委託的形參型別,形參個數和委託的返回值必須與將要繫結的方法的形參型別,形參個數和返回值一致;

public delegate  委託返回型別  委託名(形參)

例子:如上我們委託將要表示系統輸出的問候語

a.委託將要繫結的方法

複製程式碼
 public string ChinesePeople(string UserName)
        {
            string GreetContents = "您好!" + UserName;
            return GreetContents;
        }

        //English People
        public string EnglishPeople(string UserName)
        {
            string GreetContents = "Hello," + UserName + "!";
            return GreetContents;
        }
        //非英非漢
        public string OtherPeople(string UserName)
        {
            return "Sorrry,當前系統只支援漢語與英語";
        }
複製程式碼

b.由如上方法可看出,方法的返回型別為string,方法有一個string型別的形參,在定義委託時,與其保持一致即可

//定義委託
public delegate string DelegateGetGreeting(string UserName);

2.繫結方法

使用委託時,將方法名字作為引數傳遞給委託即可

1 GreetToUsers greetToUsers = new GreetToUsers();
2 GetGreetingContents(UserName, greetToUsers.ChinesePeople)

(二)委託繫結方法

1.繫結單個方法

繫結單個方法,將單個方法名字傳給委託即可

 View Code

另一種不太規範寫法:不用GetGreetingContents(string UserName,DelegateGetGreeting delegateGetGreeting)方法

 View Code

之所以不規範,主要是在專案中,不利於程式碼的模組化。

2.繫結多個方法(多播委託)

注意:繫結多個方法時,委託範圍型別必須為void型別,否則只返回最後一個繫結的值。

 繫結多個方法,採用 += 繫結

 View Code

3.解綁方法

解載繫結的方法,採用 -= 解綁

 View Code

(三)委託機制

 將如下程式碼通過反彙編工具.NET Reflector反彙編

 View Code

反彙編

 分析:

1.三個核心方法:BeginInvoke,EndInvoke和Invoke

(1)使用Invoke完成一個委託方法的封送,就類似於使用SendMessage方法來給介面執行緒傳送訊息,是一個同步方法。也就是說在Invoke封送的方法被執行完畢前,Invoke方法不會返回,從而呼叫者執行緒將被阻塞。

(2使用BeginInvoke方法封送一個委託方法,類似於使用PostMessage進行通訊,這是一個非同步方法。也就是該方法封送完畢後馬上返回,不會等待委託方法的執行結束,呼叫者執行緒將不會被阻塞。但是呼叫者也

可以使用EndInvoke方法或者其它類似WaitHandle機制等待非同步操作的完成。

總結:但是在內部實現上,Invoke和BeginInvoke都是用了PostMessage方法,從而避免了SendMessage帶來的問題。而Invoke方法的同步阻塞是靠WaitHandle機制來完成的。

提示:

最近瀏覽一篇文章,也講得不錯:http://blog.csdn.net/goodshot/article/details/6157529

要想深入瞭解,請參照《CLR Via C#》,

第二部分  事件

關於事件(event),將會從如下四個角度來分析.

1.什麼是事件

2.事件能解決什麼問題

3.怎麼使用事件

4.事件機制

 

一  什麼是事件

 談到委託,必提事件,事件本質是對委託的封裝,對外提供add_EventName(對應+=)和remove_EventName(對應-=)訪問,從而實現類的封裝性。

1.種類

強型別事件和弱型別事件

2.一些用處

(1)WebForm控制元件的Click事件。做過WebForm開發的朋友,可能對事件是非常熟悉的,如拖一個Button,雙擊,就自動在後臺生成Button的Click事件,如下圖所示。

原理:在Windows運用程式中,Button類提供了Click事件,其本質就是委託,當我們觸發Click事件時,呼叫的處理程式方法需要引數,其引數就是由委託型別來定義的。

(2)設計模式釋出/訂閱。事件是基於委託的,為委託提供了一種釋出/訂閱機制。

二 事件能解決哪些問題

1.將公有的委託變數定義為私有變數,從而滿足類的封裝性原則;

2.具有委託具有的作用;

三 如何使用事件

1.宣告委託

public delegate void DelegateGetGreeting(string UserName);

2.宣告事件

與委託宣告一樣,只不過多了一個關鍵字event

public event DelegateGetGreeting EventGreet;

3.時間註冊方法

事件註冊方法與委託註冊方法是一樣的。

1 DelegateGreet DG= new DelegateGreet();
2 //DG.delegateGetGreeting = GTU.ChinesePeople;//註冊方法
3 DG.EventGreet+= GTU.ChinesePeople;
4 DG.EventGreet += GTU.EnglishPeople;

4.呼叫事件

呼叫定義事件的方法

DG.GreetUser("小王");

完整程式碼如下:

 View Code

四 事件機制

 事件的本質就是委託,向外提供兩個訪問方法add_EventName(對應+=)和remove-EventName(對應-=),我們通過.NET Reflector反彙編工具來檢視,到底是不是這樣的。

相關推薦

委託事件簡介

轉載於:點選開啟連結 (http://www.cnblogs.com/wangjiming/p/8300103.html)本篇文章主要採用理論和程式碼例項相結合方式來論述委託和事件,涉及到一些邊界技術,如軟體架構的OCP原則(開-閉原則),軟體架構解耦,設計模式(Sender

C#委託事件學習筆記

委託事件學習筆記 本文是學習委託和事件的筆記,水平有限,如有錯漏之處,還望大神不吝賜教。 什麼是委託?從字面意思來解釋,就是把一個動作交給別人去執行。在實際開發中最常用的就是使一個方法可以當做一個引數傳遞,以便在方法中可以根據實際情況實現不同的功能。 什麼是事件?事件就是發生的事情,例如點選了一

Unity之C#——委託事件,觀察者模式,貓和老鼠事例

委託與事件,觀察者模式,貓和老鼠事例     在Unity遊戲開發中,我們經常需要在一個類中,呼叫另一個類中的方法,比如,當玩家進入到某個地方,敵人就開始攻擊玩家。這時就需要利用委託與事件,設計觀察者模式。 此處我們利用貓和老鼠來簡單描述: 程式碼如下: Ca

委託事件聯合使用

1、建立委託 /// <summary> /// 顧客走進飯店 /// 把選單給顧客 /// </summary> /// <param name="cusobj">顧客<

C#中委託事件的學習小結(一)

最近又學習了一些C#的小知識點,在此釋出部落格記錄一下。 一、委託 C#中的委託的關鍵字是delegate,我們可以使用委託型別來將已有的方法例項化出來,也可以將我們自己定義的方法作為引數來傳遞。 例如: private delegate string GetAStri

基礎知識篇:委託事件

委託是對函式的封裝,可以當做給方法的特徵指定一個名稱。而事件則是委託的一種特殊形式,當發生有意義的事的時候,事件物件 處理通知過程。 注意 1.委託是一種引用方法的型別。一旦為委託分配了方法,委託就與該方法具有完全相同的行為。 2.事件是在發生其它類或物件關注的事情的時

C#委託事件之----委託

C#委託與事件之委託 整理了一下委託的幾種使用方法,都在程式碼裡面了 using System; using System.Collections.Generic; using System.Linq; using System.Text; using Syst

基於委託事件的有限狀態機設計實現(Unity3d)

有限狀態機設計與實現 前言 最近看到一句話,就是優秀是一種習慣,所以突然就總想寫點什麼,當作是遊戲開發這條路上的學習筆記吧,另外也時刻提醒自己需要不斷努力。 什麼是狀態機? 先貼百度百科的概念內容吧: 有限狀態機,(英語:Finite-state machine

菜鳥教程C#高階教程部分理解(一)委託事件

委託與事件 委託 Delegate 所有的委託(Delegate)都派生自 System.Delegate 類。 定義一個委託,該委託可用於引用帶有完全相同引數和返回型別的方法。 委託的多播(也叫組播、委託鏈):一個委託變數可以同時繫結多個方法,每一個委託(

大白話系列之C#委託事件講解(一)

從序言中,大家應該對委託和事件的重要性有點了解了吧,雖然說我們現在還是能模糊,但是從我的大白話系列中,我會把這些概念說的通俗易懂的。首先,我們還是先說說委託吧,從字面上理解,只要是中國人應該都知道這個意思,除非委託2箇中文字不認識,舉個例子,小明委託小張去買車票。    &nbs

大白話系列之C#委託事件講解大結局

今天是大白話系列之C#委託與事件講解的大結局,也是我們最關心的,在日常的MES系統程式設計中到底怎樣使用這樣的利器,其實我們每天都在使用事件,一個窗體,一個按鈕都包含這事件,只是很少用到自己寫的委託和事件,說白了不知道如何下手,也不知道在什麼樣的場景下應用。 用到事件的地方有很多,這次講解就ME

大白話系列之C#委託事件講解(二)

什麼是事件?EVENT?點選事件?載入事件?一連串的模糊的概念衝擊著我們弱小的腦袋 那我們首先來看一下比較正統的感念吧: 事件是類在發生其關注的事情時用來提供通知的一種方式。 事件的發生一般都牽扯2個角色 事件發行者(Publisher):一個事件的發行者,也稱作是傳送者(sende

C#的委託事件

c#委託與事件 引言 委託 和 事件在 .Net Framework中的應用非常廣泛,然而,較好地理解委託和事件對很多接觸C#時間不長的人來說並不容易。它們就像是一道檻兒,過了這個檻的人,覺得真是太容易了,而沒有過去的人每次見到委託和事件就覺得心裡別(biè)得慌,混身不自在。本文中,我

委託事件的深入理解

一、委託的理解 委託是一種型別(與列舉是一樣的):特殊的地方是它指向一個方法   二、委託的使用場景:將一個方法抽象出來作為引數傳遞 class Program { static void Main(string[] args) { //MyDelegate md = (s) => {

多播委託觀察者模式聯合使用,以及委託事件的區別

首先我們先看一下多播委託: 使用委託時,首先我們宣告委託,委託語法一共有四種類型,分別時有參,無參,以及有無引數返回值。 1 public class DelegateShow //: System.MulticastDelegate,多播委託 2 { 3 public del

委託事件(1)

原創連結 網上講C#委託和事件的博文已經非常多了,其中也不乏一些深入淺出、條理清晰的文章。我之所以還是繼續寫,主要是藉機整理學習筆記、歸納總結從而理解更透徹,當然能夠以自己的理解和思路給其他人講明白更好。 另

通過委託事件監聽狀態改變來更新UI

該博文涵蓋的知識點 1. C# 委託 2. 如何利用委託監聽事件以此更新顯示 所要完成目標 我們剛開始做好的部分UI介面如下圖所示: 觀察左邊的紅色方框,我們先做了例項的姓名,頭像,slider,和Label等,在運行遊戲時候需要更新相應的屬性。 在下面的指令碼中,我們分

詳解Unity中的委託事件

回到目錄 0x00 前言 由於工作繁忙所以距離上一篇部落格已經過去一個多月的時間了,因此決心這個週末無論如何也得寫點東西出來,既是總結也是分享。那麼本文主要的內容集中在了委託的使用以及內部結構(當然還有事件了,但是受制於篇幅故分為兩篇文章)以及結合一部分Unity3D的設計思考。當然由於時間倉促,文中難免

CSharp學習筆記之十二 委託事件(續)

尼瑪,當把剛才的文章給儲存發表之後,想看看其他方面你的文章,這時候又看到了另外的一個比較不錯的文章,名字與本題同名,正覺得納悶呢,仔細一看,原來是同一作者的東西,頓時有一種被騙的感覺。這些都不重要,真心的不重要,重要的是這些東西我們都能夠學到比較多的東西。所以,這裡就又將那

快速理解C#中的委託事件

以下內容只是個人理解,僅供參考。 什麼是委託? 先看最簡單的委託例子: namespace DelegateTest { public delegate void MessageDelegate(string name); class Program