什麼是委託?
msdn中給出的答案是「委託是一種引用方法的型別。」
看到這個答案,相信很多人都會覺得不知所云,能夠理解的人,您一定已經對委託很熟悉了,所以後面的內容也許並不適合您。
實際上,從這個答案中,我們只需要明白兩個問題就可以了,第乙個問題就是「委託是一種型別」,既然委託是一種型別,那麼,從直觀上看,委託型別和.net中的其它型別,如string、datetime,都一樣,都是可以用來宣告具體的型別例項的。第二個問題就是「引用方法的型別」,這句話就告訴了我們,象string可以宣告乙個字串物件,datetime可以宣告乙個時間物件一樣,委託可以宣告乙個引用方法的物件。
什麼是引用方法的物件?學過c或c++的人都知道函式的指標,這個指標可以指向乙個具體函式,沒錯,使用了委託定義出來的物件就象乙個函式的指標,但它可以做更多的事情。呃...有人扔磚頭了,記住啊,我從來沒說過委託就是函式的指標,我只是打了個比方哦。
你不知道什麼是c或c++?你**來的?火星...好了,怕了你了。如果你沒聽說過函式的指標,那麼你總知道什麼是函式或者方法吧?ok,委託型別可以宣告乙個物件,這個物件可以和乙個函式或方法進行關聯,然後你就可以用這個委託物件去操作你關聯的函式或方法了。明白了嗎?你問我為什麼要用委託去操作關聯的函式或方法而不是直接去呼叫它們?呃...good question! 請帶著你的疑問往下看吧,後面我要告訴大家什麼地方能夠用到委託以及如何去用。如果你能看明白了,那麼我想你自己一定就會得到這個問題的答案了。
委託用途之一:函式(方法)呼叫
既然委託是跟方法有關的型別,我們就先來看看如何來使用委託進行方法的呼叫。先來定義乙個委託型別:
public
delegate
inttestdelegate(int i1, int i2);
定義委託型別使用delegate關鍵字,就像定義其它的型別使用class關鍵字一樣。如果我們忽略掉delegate關鍵字,那麼這個定義看上去就像宣告了乙個函式。的確,定義乙個委託型別,除了要指定它的名字外,就是要說明這個委託型別所能呼叫的函式是什麼樣子的(都有哪些引數,返回值是什麼型別)。如果你忘記了委託定義的格式,就想想函式是如何定義的吧。很多文章中都提到了,委託型別要與它想要呼叫的函式具有相同的簽名,這個相同的簽名,指的就是相同的引數型別和返回型別。
我們宣告的這個testdelegate委託型別就是用來呼叫這樣的函式--具有兩個int引數並且返回型別為int型別。
定義了委託型別之後,我們如何使用它呢?委託型別的使用和其它的型別一樣,需要例項化乙個具體的委託物件。就象這樣:
1:public
delegate
inttestdelegate(int i1, int i2);
2:
3:private
void button1_click(object sender, eventargs e)
4:
7:
8:private
int add(int i1, int i2)
9:
看第5行,象例項化其它的型別一樣,我們例項化了乙個testdelegate型別testdeleinstance,在它的建構函式中,需要指定這個委託型別的例項(testdeleinstance)要呼叫的是哪個具體的函式。
下面如何通過這個委託的例項呼叫函式add呢?
1:private
void button1_click(object sender, eventargs e)
2:
我們可以使用第5行的方法,直接呼叫這個委託,這使得委託看上去更像乙個函式;也可以使用第6行的方法,呼叫這個委託物件的invoke方法。無論使用哪種方法,最終都會執行add這個函式(當然委託還有非同步呼叫的方法,這個會在後面陸續講解)。可是我們這麼折騰了半天,為什麼不直接呼叫add函式呢?別著急,接著看完下面這段,你可能就會有自己的想法了。
假設我們定義了乙個類a
1:public
class a
2:
9: }
這樣,我們可以通過a.getresult()方法返回a的兩個屬性op1和op2的和。這時,如果我想要a.getresult()方法返回兩個屬性的差怎麼辦?很簡單,修改getreult方法,讓它返回op1 - op2。如果這個類a是你發布的乙個產品,你的使用者希望自己控制getresult方法的邏輯(或許他想返回兩個屬性的最小值,誰知道呢。),又該怎麼辦呢?我們看修改後的類a:
1:public
class a
2:
9: }
沒錯,我們給getresult方法新增了乙個引數,乙個testdelegate委託型別的引數。什麼?你說我從來沒有告訴過你委託可以做引數?拜託,再說一次,委託型別也是型別,跟string一樣,其它型別能出現的地方,委託型別也可以。(實際上委託型別比string簡單多了,看看string型別有多少成員~~)
現在我們再看看呼叫a的getresult方法會發生什麼?呼叫者需要提供乙個testdelegate委託型別的例項,這個例項會指向呼叫者自己定義好的、乙個滿足testdelegate委託型別的簽名的方法(這句話有點長,多看兩遍啊。簽名是什麼?往前面看,前面說過。)。也就是說,現在這個getresult方法,實際上執行的是呼叫者自己定義的乙個函式(方法),那麼,呼叫者想如何控制這個方法的邏輯,就隨他去吧。
1:public
class b
2:
10:
11:int max(int i1, int i2)
12:
15: }
上面的**說明,類b呼叫類a的getresult方法的時候,指定了由類b自己的max方法去處理getresult的邏輯。你看不明白
13:return i1 > i2 ? i1 : i2;
這段**用一種更簡潔的語法表達了這樣的乙個意思:i1大於i2嗎?如果答案是yes,那麼請返回i1,否則返回i2吧。
將委託作為引數,給予了類更多的靈活性,也使得呼叫者有的更多的選擇。看到這裡,請回想一下當初的問題,函式直接呼叫和使用委託呼叫,是不是有些不一樣呢?
1:void testa()
2:
mysql很簡單 MySQL入門很簡單
基本資訊 商品名稱 mysql入門很簡單 附光碟 出版社 清華大學isbn號 9787302243625頁數 466 內容提要 目錄 篇 mysql資料庫基礎 1.1 資料庫理論基礎 1.1.1 資料儲存方式 1.1.2 資料庫泛型 1.1.3 資料庫在開發中作用 1.2 資料庫技術構成 1.2.1...
GDI 水印 很簡單很簡單的版
using system using system.collections.generic using system.componentmodel using system.data using system.drawing using system.linq using system.text u...
成功很簡單
十年裡四處碰壁 問題是學術不精,沒有恆心和毅力,十年不短,一荒而過,不但沒進步還在倒退。如今要閉門休學,一定,不學成,不出來見人,做好準備,以死的心態去學。浪費十年的時間,現在開始不再浪費一分一秒 堅決做到以下幾點 1.不上網閒逛 2.不看電視電影,不玩遊戲 3.不看任何娛樂節目 4.不看任何比賽過...