委託的發展 一

2022-04-06 16:11:12 字數 3059 閱讀 3380

zzz這幾天一直在看委託,

一直從1.0的委託看到了3.0的蘭姆達表示式與linq。

寫個部落格記錄一下,雖然委託的多種用法都沒有研究透徹,以後慢慢研究吧!

一提起委託,如果你是c程式設計師,肯定會想到 函式指標 這個術語.實際上委託在某種程度上提供了間接的方法。

換言之,不需要直接指定乙個要執行的行為,而是將這個行為用某種方式"包含"在乙個物件中。這個物件可以像其他任何的物件那樣使用,再該物件中,可以執行封裝的操作。

可以選擇將委託型別看做之定義了乙個方法的介面,將委託的例項看做實現了那個介面的乙個物件。

簡單委託的構成,為了讓委託做某事,必須滿足四個條件:

*宣告委託型別

*必須有乙個方法包含了要執行的**;

*必須建立乙個委託例項

*必須呼叫(invoke)委託例項

慢慢來,乙個個的看:

委託型別實際上只是引數型別的乙個列表以及乙個返回型別。他規定了型別的例項能表示的操作。

例如:

delegate

void stringdelegate(string val);

這段**指出,如果要建立 stringdelegate 這樣乙個例項,必須要只帶乙個引數(string),並且無返回值 void 方法。

基本思路就是,要確保在呼叫invoke乙個委託例項時,使用的引數完全匹配,而且以我們希望的方式返回值(如果有的話)。

void test1(string

x);void test2(int

x);void test3(string x, string

y);int test4(string

x);void test5(object x);

這些個方法有那幾個滿足呢?

首先test1完全符合要求,所以用它建立乙個委託例項。

第二個test2雖然也有乙個引數但是不是string型別的,所以不相容。

第三個test3引數數量不匹配,不相容。

第四個test4引數型別個數匹配,但返回型別不是void,所以不相容。

第五個就比較有意思了,返回型別匹配,但是引數型別不是string 而是 object,大家都知道string是由object派生的。把這個方法作為乙個委託例項應該合情合理啊!

但是c#1要求委託必須具有完全相同的引數型別。所以在c#1中這個也是不相容的!

如果給委託加入乙個例項,首先他必須與委託有相同的返回值,引數個數,引數型別 必須一致。

至於具體用什麼形式的表示式來建立委託例項,取決於操作的例項方法還是靜態方法。

例項方法:

instancemethods instance = new

instancemethods(); //例項化乙個instancemethods類

stringdelegate delegatestr = new stringdelegate (instance.methods); //stringdelegate委託例項化,在括號裡必須點出符合條件的方法
靜態方法:

stringdelegate delegatestr = new stringdelegate (staticmethods.mehtods); //例項化stringdelegate委託,靜態方法直接點出來符合條件的方法
如果是靜態方法,指定型別名稱就可以了。如果是例項方法,就必須先建立型別(或者他的派生型別)的乙個例項。和平時呼叫方法是一樣的,這個物件被稱為操作的目標。

單純建立乙個委託例項卻不在某一刻呼叫他是麼有什麼意義的,具體看看最後一步-----呼叫。

在委託型別中這個方法以委託型別的形式出現,並且具有委託型別宣告中指定的相同引數列表和返回型別。

所以,在我們的例子中,有乙個這樣的方法:

void invoke(string val)
呼叫invoke會執行委託例項的操作,向他傳遞在呼叫invoke時指定的任何引數。另外如果返回值不是void,還要返回操作的返回值。

很簡單不是嗎?如果有乙個委託型別的變數,就可以把它視為方法本身。觀察者有不同時間發生的事件構成乙個時間鏈,就很容易理解這一點。

c#1的委託就是這麼簡單!所有原料已經齊備,接著將clr預熱到200°c,將所有東西攪拌在一起,看看會發生什麼。

對了忘記給大家說一下委託的新增例項與刪除例項了。。。

system.delegate型別的靜態方法combine和remove負責建立新的委託例項。

其中combine負責將兩個委託的呼叫列表連線到一起(就是新增乙個例項)

而remove負責從乙個委託例項中刪除另乙個例項的呼叫列表(就是刪除乙個例項)

現在很少在c#**中看到delegate.combine的顯示呼叫了,大家一般都這樣寫+=跟-=操作符

其實執行的時候會轉換成delegate.combine,看一下下面的x委託加入y例項

乙個非常簡單的轉換過程,但它使**變得整潔多了。

除了合併新增例項,也可以刪除例項使用delegate.remove方法刪除乙個指定的例項,平時都是用簡寫-=來實現。

呼叫委託例項時,他的所有操作都順序執行。如果委託的簽名是乙個非void的返回型別的話。

則invoke的返回值是 最後乙個 操作的返回值。

如果呼叫列表中的任何乙個操作丟擲異常,都會阻止後續的操作。

例如呼叫乙個委託,他的操作列表是[a,b,c],但是b丟擲了異常,這個異常會立刻傳播,操作c不會執行。

*委託封裝了包含特殊返回型別和一組引數的行為,類似包含單一方法的介面。

*委託型別宣告中所描述的型別簽名決定了哪個方法可用於建立委託例項。同時決定了呼叫的簽名

*為了建立委託例項,需要乙個方法以及(對於例項方法來說)呼叫的目標。

*委託例項都包含乙個呼叫列表-----乙個操作列表

*委託例項可以合併到一起,也可以從乙個委託例項中刪除另乙個

*事件不是委託的例項,只是成對的add/remove方法(類似於屬性的取值方法/賦值方法)

委託的發展

下例演示了c 1.0到3.0委託的建立過程 public partial class delegate default2 system.web.ui.page del lambda表示式建立的委託 del del static void w public delegate void testdele...

委託的發展 二

嗯 其實在c 1看來委託語法看起來似乎並不太壞 語言以圍繞delegate.combine,delegate.remove以及委託例項的呼叫提供了語法糖。表面上一切都在正常的軌道上,但是感覺不太對。很難確切的描述c 1的委託建立表示式為什麼會令人不快,但他們確實如此。在c 1中我們先寫好一連串事件處...

委託發展史 三

通過c 2極大的簡化了委託的使用。如果僅僅是為了簡化事件的訂閱以及增強可讀性,這些技術確實已經足夠了。但是,c 2中的委託仍然過於臃腫 一頁充滿匿名方法的 讀起來真讓人難受,你也肯定不願意經常在乙個語句中放入多個匿名方法吧。c 3可以說是乙個工業革命。從許多方面lambda表示式都可以看做是c 2的...