我明白委託封裝方法調用。不過,我很難理解他們的需求。爲什麼要使用代表,他們設計了什麼樣的情況?與代表達成什麼協議?
回答
委託本質上是一個方法指針。委託讓我們創建一個引用變量,但不是引用一個類的實例,而是引用類中的方法。它引用具有返回類型並具有與該委託指定的相同參數的任何方法。這是一個非常有用的事件。爲了徹底閱讀,我建議您閱讀Head First C#(Andrew Stellman和Jennifer Greene撰寫)中的主題。它精美地解釋了委託主題以及.NET中的大多數概念。
真棒描述.. – 2010-09-21 14:25:03
代表經常用於Events
。根據MSDN,在.NET委託設計用於以下情況:使用
- 的三項賽的設計模式。
- 需要封裝一個靜態方法。
- 調用者無需訪問實現該方法的對象上的其他屬性,方法或接口。
- 簡單的組成是期望的。
- 一個類可能需要一個以上的實施方法
從MSDN另一公把解釋的methodimplementation的,
一個使用 單方法接口而不是很好的例子代表 的代表是
IComparable
或IComparable
。IComparable
聲明 CompareTo方法,該方法返回一個指定小於,等於 到的 整數,或者返回相同類型的兩個對象之間的關係 。 IComparable可以用作排序算法的基礎 ,而使用 代表比較方法作爲排序算法的基礎 將是 有效,這是不理想的。由於 比較的能力屬於 類,並且比較算法 在運行時不會更改,因此單方法接口是ideal.single-method接口是理想的。
由於.NET 2.0它也被用於anonymous functions。
維基百科有關於委託模式一個很好的解釋,
在軟件工程中,委託模式是在面向對象的程序設計模式,其中一個對象,而不是執行其既定任務之一,代表該任務發送給關聯的助手對象。它通過了負面影響,可以這麼說(技術上來說,是一種責任倒置)。輔助對象稱爲委託。委託模式是構成其他軟件模式(如組合(也稱爲聚合),混合和方面)的基本抽象模式之一。
好,一些常見的用途:
- 事件處理程序(在UI代碼很常見的 - 「當單擊該按鈕時,我想這個代碼執行」)從異步調用
- 回調
- 提供的螺紋(或線程池)用新的任務來執行
- 指定LINQ突起/條件等
不要認爲它們是封裝方法調用。把它們想象成封裝一些具有特定簽名的任意行爲/邏輯。 「方法」部分有些不相關。
另一種思考委託類型的方法是作爲單一方法的接口。一個很好的例子就是IComparer<T>
接口及其雙重代理類型Comparison<T>
。他們代表了相同的基本想法;有時候更容易將其表示爲委託,而其他時候界面使生活更輕鬆。 (當然,您可以輕鬆地編寫代碼來在兩者之間進行轉換。)
代表允許您傳遞對方法的引用。一個常見的例子是將比較方法傳遞給排序函數。
它們的設計意義非常廣泛,因爲當你知道需要調用其他代碼的代碼時 - 但在編譯時你不知道其他代碼可能是什麼。
作爲示例,請考慮使用委託的Windows窗體Button.Click事件。 Windows窗體程序員知道,當按下按鈕時,你會想要發生某種事情,但他們無法確切知道你想要做什麼......它可能是任何東西!
因此,您創建一個方法並將其分配給一個委託並將其設置爲該事件,並且在那裏。這是代表們的基本推理,儘管他們有很多其他相關的好用途。
如果您需要在運行時決定調用哪種方法,那麼您使用委託。然後代理將在運行時響應某些動作/事件,並調用適當的方法。這就像發送一個「代表」到你不想參加的婚禮:-)
C人會認識到這是一個函數指針,但不要被這裏的術語所困擾。所有委託人(並且實際上是一種類型)都提供了方法的簽名,稍後將調用該方法來實現適當的邏輯。
的「畫報C#」一書由丹·索利斯提供了學習這個概念的最簡單的切入點,我所遇到的:
http://www.amazon.com/Illustrated-2008-Windows-Net-Daniel-Solis/dp/1590599543
雖然我碰巧很喜歡A按...有什麼用鏈接一個「尚未公佈」的書? – WernerCD 2010-09-20 13:48:35
@WernerCD,感謝您的單挑。有兩個以前的版本,所以更新鏈接:-) – IrishChieftain 2010-09-20 13:50:46
我絕對愛C#圖解2008年,恰好等待2010年發佈......這是我第一次注意到嘿:) – WernerCD 2010-09-20 14:13:57
委託是典型的對象引用和指針的組合到對象的類方法之一(可以爲靜態方法創建委託,在這種情況下,沒有對象引用)。可以調用委託而不考慮包含對象的類型,因爲包含的方法指針保證對包含的對象有效。
爲了理解代表背後的一些用處,回想一下C語言和函數的printf「家族」。假設你想擁有一個通用版本的「printf」,它不僅可以是用作printf,fprintf,sprintf等,但可以將其輸出發送到串行端口,文本框,TCP端口,cookie結霜機器或其他任何設備,而無需預先分配緩衝區。顯然,這樣的函數需要接受字符輸出例程的函數指針,但這本身通常是不夠的。
一個典型的實現(不幸的是不標準化)將有一個通用的gp_printf例程,它接受(除了格式字符串和輸出參數)void指針和指向一個函數的指針,該函數接受一個字符和一個void指針。 gp_printf例程本身不會使用傳入的void指針,但會將它傳遞給字符輸出函數。然後,該函數可以將指針轉換爲FILE *(如果gprint_printf被fprintf調用)或char **(如果它被sprintf調用)或SERIAL_PORT *(如果它被serial_printf調用),或者。
請注意,因爲任何類型的信息都可以通過void *傳遞,所以gp_printf可以做什麼沒有限制。但是,如果在void *中傳遞的信息不是函數期望的信息,那麼可能會導致未定義的行爲(即可能非常糟糕的事情)。調用者的責任是確保函數指針和void *正確配對;系統中沒有任何東西可以防止不正確的使用。
在.net中,委託可以提供函數指針和void *上面的組合功能,還有額外的好處是委託的構造函數可以確保數據是函數的正確類型。一個方便的功能。
過度簡化:我會說,委託是一個函數的佔位符,直到某些事情將某個實際功能分配給該委託時爲止。調用未分配的委託會引發異常。
混亂髮生是因爲定義,聲明,實例化和委託調用之間通常沒有什麼區別。
定義:
在命名空間將這個就像任何類定義。
public delegate bool DoSomething(string withThis);
這相當於類定義,因爲您現在可以聲明此代理的變量。
聲明:
把這是一個函數例程,就像你會聲明任何變量。
DoSomething doSth;
實例化和分配:
通常你會連同申報做到這一點。
doSth = new DoSomething(MyDoSomethingFunc);
「新的DoSomething(..)」是實例。 doSth = ...是任務。
請注意,您必須已經定義了一個名爲「MyDoSomething」功能,將一個字符串返回一個布爾值。
然後,你可以調用函數。
調用:
bool result = doSth(myStringValue);
活動:
你可以看到事件進來:
由於類的成員通常是基於定義的聲明。
像
class MyClass {
private int MyMember;
}
事件是基於委託聲明:
public delegate bool DoSomething(string withWhat);
class MyClass {
private event DoSomething MyEvent;
}
與前面的例子不同的是,事件是「特殊」:
- 您可以致電未分配的事件而不引發異常。
- 可以將多個功能的事件。然後他們將依次被調用。如果其中一個調用引發異常,其他調用將無法播放。
他們真的是代表陣列的語法糖。
的一點是當然的東西/別人會做分配給你的。
- 1. 代表財產與協議採用
- 2. 什麼是聯邦協議?
- 3. 什麼是xmlsocket://協議?
- 4. 什麼是USB協議棧?
- 5. 什麼是COP3協議?
- 6. 什麼是Xdata協議?
- 7. 什麼是協議棧?
- 8. 什麼是hm://協議?
- 9. 什麼是SMPP協議?
- 10. 什麼是webcal協議?
- 11. 什麼是RCE協議?
- 12. 什麼協議XDocument.Load用戶
- 13. Objective C代表和協議
- 14. 傻瓜協議和代表
- 15. Objective-C雙代表協議
- 16. 代表和協議目標
- 17. 0-9-1在AMQP 0-9-1協議中代表什麼
- 18. gitsharp克隆http協議失敗,但git協議成功!爲什麼?
- 19. 協議緩衝如何與傳統協議代碼交互
- 20. 讓我們達成協議JavaScript代碼不起作用
- 21. 與ActiveSync協議
- 22. 什麼是MessagePack /協議緩衝區的傳輸協議?
- 23. 什麼是「網際協議,僞協議號碼」?
- 24. uwsgi協議和wsgi協議有什麼區別?
- 25. 爲什麼Objective-c協議採用其他協議?
- 26. Firebase XMPP協議與HTTP協議
- 27. Swift協議和協議擴展與CollectionType
- 28. 二進制協議與文本協議
- 29. 正則表達式跳過協議url
- 30. 正則表達式PHP的URL協議
每當我讀到這個問題,我聽到它的傑裏宋飛的聲音的稱號。 – Jess 2010-09-20 13:49:52