2010-09-20 47 views
7

我明白委託封裝方法調用。不過,我很難理解他們的需求。爲什麼要使用代表,他們設計了什麼樣的情況?與代表達成什麼協議?

+7

每當我讀到這個問題,我聽到它的傑裏宋飛的聲音的稱號。 – Jess 2010-09-20 13:49:52

回答

11

委託本質上是一個方法指針。委託讓我們創建一個引用變量,但不是引用一個類的實例,而是引用類中的方法。它引用具有返回類型並具有與該委託指定的相同參數的任何方法。這是一個非常有用的事件。爲了徹底閱讀,我建議您閱讀Head First C#(Andrew Stellman和Jennifer Greene撰寫)中的主題。它精美地解釋了委託主題以及.NET中的大多數概念。

+0

真棒描述.. – 2010-09-21 14:25:03

4

代表經常用於Events。根據MSDN,在.NET委託設計用於以下情況:使用

  • 的三項賽的設計模式。
  • 需要封裝一個靜態方法。
  • 調用者無需訪問實現該方法的對象上的其他屬性,方法或接口。
  • 簡單的組成是期望的。
  • 一個類可能需要一個以上的實施方法

從MSDN另一公把解釋的methodimplementation的,

一個使用 單方法接口而不是很好的例子代表 的代表是IComparableIComparableIComparable聲明 CompareTo方法,該方法返回一個指定小於,等於 到的 整數,或者返回相同類型的兩個對象之間的關係 。 IComparable可以用作排序算法的基礎 ,而使用 代表比較方法作爲排序算法的基礎 將是 有效,這是不理想的。由於 比較的能力屬於 類,並且比較算法 在運行時不會更改,因此單方法接口是ideal.single-method接口是理想的。

由於.NET 2.0它也被用於anonymous functions

維基百科有關於委託模式一個很好的解釋,

在軟件工程中,委託模式是在面向對象的程序設計模式,其中一個對象,而不是執行其既定任務之一,代表該任務發送給關聯的助手對象。它通過了負面影響,可以這麼說(技術上來說,是一種責任倒置)。輔助對象稱爲委託。委託模式是構成其他軟件模式(如組合(也稱爲聚合),混合和方面)的基本抽象模式之一。

8

好,一些常見的用途:

  • 事件處理程序(在UI代碼很常見的 - 「當單擊該按鈕時,我想這個代碼執行」)從異步調用
  • 回調
  • 提供的螺紋(或線程池)用新的任務來執行
  • 指定LINQ突起/條件等

不要認爲它們是封裝方法調用。把它們想象成封裝一些具有特定簽名的任意行爲/邏輯。 「方法」部分有些不相關。

另一種思考委託類型的方法是作爲單一方法的接口。一個很好的例子就是IComparer<T>接口及其雙重代理類型Comparison<T>。他們代表了相同的基本想法;有時候更容易將其表示爲委託,而其他時候界面使生活更輕鬆。 (當然,您可以輕鬆地編寫代碼來在兩者之間進行轉換。)

0

代表允許您傳遞對方法的引用。一個常見的例子是將比較方法傳遞給排序函數。

5

它們的設計意義非常廣泛,因爲當你知道需要調用其他代碼的代碼時 - 但在編譯時你不知道其他代碼可能是什麼。

作爲示例,請考慮使用委託的Windows窗體Button.Click事件。 Windows窗體程序員知道,當按下按鈕時,你會想要發生某種事情,但他們無法確切知道你想要做什麼......它可能是任何東西!

因此,您創建一個方法並將其分配給一個委託並將其設置爲該事件,並且在那裏。這是代表們的基本推理,儘管他們有很多其他相關的好用途。

0

如果您需要在運行時決定調用哪種方法,那麼您使用委託。然後代理將在運行時響應某些動作/事件,並調用適當的方法。這就像發送一個「代表」到你不想參加的婚禮:-)

C人會認識到這是一個函數指針,但不要被這裏的術語所困擾。所有委託人(並且實際上是一種類型)都提供了方法的簽名,稍後將調用該方法來實現適當的邏輯。

的「畫報C#」一書由丹·索利斯提供了學習這個概念的最簡單的切入點,我所遇到的:

http://www.amazon.com/Illustrated-2008-Windows-Net-Daniel-Solis/dp/1590599543

+0

雖然我碰巧很喜歡A按...有什麼用鏈接一個「尚未公佈」的書? – WernerCD 2010-09-20 13:48:35

+0

@WernerCD,感謝您的單挑。有兩個以前的版本,所以更新鏈接:-) – IrishChieftain 2010-09-20 13:50:46

+0

我絕對愛C#圖解2008年,恰好等待2010年發佈......這是我第一次注意到嘿:) – WernerCD 2010-09-20 14:13:57

0

委託是典型的對象引用和指針的組合到對象的類方法之一(可以爲靜態方法創建委託,在這種情況下,沒有對象引用)。可以調用委託而不考慮包含對象的類型,因爲包含的方法指針保證對包含的對象有效。

爲了理解代表背後的一些用處,回想一下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 *上面的組合功能,還有額外的好處是委託的構造函數可以確保數據是函數的正確類型。一個方便的功能。

1

過度簡化:我會說,委託是一個函數的佔位符,直到某些事情將某個實際功能分配給該委託時爲止。調用未分配的委託會引發異常。

混亂髮生是因爲定義,聲明,實例化和委託調用之間通常沒有什麼區別。

定義:
在命名空間將這個就像任何類定義。

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. 可以將多個功能的事件。然後他們將依次被調用。如果其中一個調用引發異常,其他調用將無法播放。

他們真的是代表陣列的語法糖。

的一點是當然的東西/別人會做分配給你的。