C 多播委託與事件

2021-09-26 02:27:35 字數 3316 閱讀 9019

1.發布-訂閱模式

委託本身是乙個更大的模式的基本單位,這個模式稱為發布-訂閱。委託的使用及其對publish-subscribe模式的支援是需要學習的重點。雖然,很多問題都可以單獨用委託來實現,但是事件構造提供了額外的「封裝」,使publish-subscribe模式更容易實現,更不容易出錯。

2.多播委託與觀察者模式

觀察者模式:需要將單一事件的通知廣播給多個訂閱者

乙個委託值是可以引用一系列方法的,這些方法順序呼叫,就是多播委託(multicast delegate)。利用多播委託,單一事件的通知就可以發布給多個訂閱者。

示例:定義發布者和訂閱者,(發布者裡包含委託型別)然後將其聯絡起來,聯絡的方式就是使用+=來賦值,為委託註冊訂閱者,之後發布者和訂閱者就聯絡起來了,然後要做的就是呼叫委託了,也就是去建立需要發布的資訊。

實現:定義訂閱者

class cooler

public float temperature

public void ontemperaturechanged(float newtemperature) else}}

class heater

public float temperature

public void ontemperaturechanged(float newtemperature)

else

}}

定義發布者,並通過呼叫委託來通知訂閱者

使用+=操作直接複製,向ontemperaturechange委託註冊兩個訂閱者,然後通過currenttemperature在溫度變化時呼叫委託通知所有的訂閱者(訂閱者的新增在後面)。這裡的action是內建的泛型委託,我們也可以根據自己的需要自定義委託型別,然後建立乙個發布者;

public class thermostat 

public float currenttemperature

set

} }private float _currenttemperature;

}

連線發布者和訂閱者(新增訂閱者)

thermostat thermostat = new thermostat();

heater heater = new heater(60);

cooler cooler = new cooler(80);

thermostat.ontemperaturechange += heater.ontemperaturechanged;

thermostat.ontemperaturechange += cooler.ontemperaturechanged;

總結:該模式的思想和所有語言中的事件註冊分發的思想是一致的,關鍵是要明確發布者和訂閱者,以及通過什麼來聯絡發布者和訂閱者從而實現註冊關係,因為發布者即執行分發操作,訂閱者即執行收到分發後的操作;

在多播委託中使用乙個委託變數來進行分發操作,然後使用其它函式例項新增到這個委託變數上來實現「註冊」;而在事件分發中,往往是宣告乙個事件名,發布者分發時使用該事件進行分發,訂閱者通過註冊該事件來完成註冊;(觀察者模式實現非同步操作)

system.multicastdelegate是從system.delegate派生的,multicastdelegate類包含了乙個物件引用和乙個方法引用,這和它的delegate基類一樣,但除此之外,它還包含對另乙個system.multicastdelegate物件的引用;實際上,multicastdelegate類維護這乙個delegate物件鍊錶,呼叫多播委託時,鍊錶中的委託例項會被順序呼叫,而且委託按照它們新增時的順序呼叫。

a.封裝訂閱,如果使用賦值操作符將乙個委託賦給另乙個,那麼就可能會出現意外的取消原訂閱者;

b.封裝發布,事件確保只有包容類才能觸發事件通知,而委託的問題就在於封裝不充分,其它類也可能造成改變;

而且普通委託很容易忘記在呼叫委託之前檢查null值,這會引發乙個非預期的異常值。但是通過event關鍵字提供的封裝,可以在宣告時採用乙個替代方案,也就是賦值delegate{},即空委託,這樣就可以引發事件但不必檢查是否有訂閱者。

c#用event關鍵字解決上述兩個,雖然event關鍵字看起來像乙個字段修飾符,但是event定義的是乙個新的成員型別;

如下,使用event定義了乙個public欄位,看起來是削弱了封裝,而不是我們想要的增強封裝;但是我們新增了event關鍵字,它提供了我們需要的全部封裝,新增了event關鍵字之後,會禁止為乙個public委託字段使用賦值操作,同時提供了必要的封裝來放置任何外部類發布乙個事件或者取消之前不是由其新增的訂閱者。

public class thermostat

public float newtemperature

}public event eventhandlerontemperaturechange;

public float currenttemperature

set}

}private float _currenttemperature;

}

編碼規範:

public delegate void eventhandler(object sender, teventargs e)

where teventargs : eventargs

action是乙個泛型委託,它需要兩個新引數,乙個代表傳送者,乙個代表事件資料; 

sender是object型別的,是對發布者物件的乙個引用,第二個引數是system.systemargs型別的,包含了事件的附加資料;呼叫委託的方式和以前幾乎完全一樣,只是要提供附加的引數;

事件限制外部類只能通過+=操作符向發布者新增訂閱方法,並用-=操作符取消訂閱,除此之外的任何事情都不允許做,而且新增與取消訂閱就是對委託鍊錶的操作;

編譯器為+=和-=生成的**是可以自定義的,假如改變ontemperaturechange委託的作用域,使它成為protected而不是private,那這樣從thermostat派生的類也可以直接訪問委託,而不用像外部類一樣受到限制,而且c#允許新增自定義的add和remove塊,為事件封裝各個組成部分提供獨特的實現,比如委託鍊錶預設都是尾插法,可以修改為頭插法,以下為簡單示例:

public event eventhandlerontemperaturechange 

remove

}protected eventhandler_ontemperaturechange;

多播委託與事件

我們通過委託可以實現把方法作為引數,傳遞給委託執行。同樣,我們的委託也可以依次執行多個方法,此時就需要我們的多播委託了。沒有接觸多播委託之前,我們呼叫多個方法的委託定義如下 returnwithpara para new returnwithpara showid 當前類的方法 returnwith...

委託 多播委託 event 事件

委託 多播委託 意義 多播委託有啥用呢?乙個委託例項包含多個方法,可以通過 去增加 移除方法,invoke時可以按順序執行全部動作 多播委託 任何乙個委託都是多播委託型別的子類,可以通過 去新增方法 給委託的例項新增方法,會形成方法鏈,invoke時,會按順序執行系列方法 給委託的例項移除方法,從方...

c 委託 與多播委託delegate

委託又叫匿名函式,首先我們來說為什麼要使用委託 委託到底是什麼 舉乙個例子 我想求煉表裡少於10的數的和,getsum static int getsum listlist return sum 我又想求煉表裡所有奇數的和,那麼是否是又要寫乙個函式getsum2 來求呢 static int get...