[英]When to use callbacks instead of events in c#?
請原諒我這是一個愚蠢的問題,我承認我沒有多想過。
但是,您何時願意使用回調(即傳入Func或Action),而不是暴露和使用事件?
UPDATE
這個問題的動機是以下問題:
我有一個ThingsHandler類,可以與ThingEditor關聯。 ThingsHandler處理事物列表,知道它們的順序,哪一個是“當前的”,添加或刪除新的等等。
ThingEditors只能修改一件事。
當用戶選擇要編輯的新Thing時,ThingsHandler需要提醒ThingEditor,當用戶說“完成”時,ThingEditor需要提醒ThingsHandler。
困擾我的是讓這兩個類彼此引用 - 雖然我猜這是不可避免的 - 或者綁定到兩個方向的事件。 我想知道在一個方向上使用回調是否“更清潔”。
我懷疑這有一種設計模式,並為我的無知(和懶惰)謙卑地道歉。
雖然到目前為止其他答案看似合理,但我會采取更具哲學性的方法。
類是一種對特定域中的特定類型的事物進行建模的機制 。 編寫類的內部細節以將機制的實現細節與正在建模的語義混淆時非常容易。 我的意思的一個簡短例子:
class Giraffe : Mammal, IDisposable
{
public override void Eat(Food f) { ... }
public void Dispose() { ... }
}
請注意我們如何將現實世界的物體(長頸鹿是一種哺乳動物,長頸鹿吃食物)與實施細節混為一談(長頸鹿的一個實例是一個可以用“使用”處理的物體。 “聲明”。 我保證,如果你去動物園,你將永遠不會看到長頸鹿被處理使用聲明。 我們把這里的水平搞混了,這是不幸的。
我嘗試使用事件(和屬性)作為語義模型的一部分,並使用回調方法(和字段)作為機制的一部分 。 我會讓GaveBirth成為長頸鹿的事件,因為這是我們試圖捕捉的真實世界長頸鹿行為模型的一部分。 如果我有一些機制,比如說,我想實現一個順序遍歷樹遍歷算法,它走遍了長頸鹿的家譜,並在每一個上調用一個方法,那么我會說這顯然是一個機制,而不是一部分該模型,並使其成為一個回調,而不是試圖將其塞進事件模型中。
我使用回調在少數情況下,我知道這將只火一次,回調是具體到一個方法調用 (而不是一個對象實例) -例如,作為異步方法的返回部分。
對於靜態實用程序方法尤其如此(因為您沒有實例,並且在不小心使用並且要避免時靜態事件是致命的),但當然另一種選擇是使用事件創建類實例。
通常,如果需要 ,我使用回調,而當它應該是可選的時使用事件。 如果您期望總是聽某事,請不要公開活動。
考慮以下:
public class MyClass_Event
{
public event EventHandler MakeMeDoWork;
public void DoWork()
{
if (MakeMeDoWork == null)
throw new Exception("Set the event MakeMeDoWork before calling this method.");
MakeMeDoWork(this, EventArgs.Empty);
}
}
與:
public class MyClass_Callback
{
public void DoWork(EventHandler callback)
{
if (callback == null)
throw new ArgumentException("Set the callback.", "callback"); // better design
callback(this, EventArgs.Empty);
}
}
代碼幾乎與回調可以作為null傳遞相同,但至少拋出的異常可能更相關。
當一個對象希望接收單個通知時(例如,運行異步數據讀取然后使用結果調用您),回調就很好。
事件適用於可由任意數量的偵聽器接收的重復通知。
在OO設計和類耦合方面,回調接口和事件之間沒有太大區別。
但是,我喜歡這樣的事件:類是需要對那些有興趣傾聽的人(通常是多件事)和特定類請求異步操作的回調“大喊大叫”的事情。
無論您使用什么,在代碼庫中始終如一地使用它們!
當我打算調用函數一次或使用Lambda表達式時,我會使用Func
或Action
。
事件可以多次注冊,有時是理想的。 如果你想要多個回調,那么必須為回調實現一個注冊系統。
一個例子是回調應該返回一些東西。 例如(愚蠢的例子):
public int Sum(Func<int> callbackA, Func<int> callbackB) {
return callbackA() + callbackB();
}
public void UseSum() {
return sum(() => 10, () => 20);
}
好吧,我認為它們是一樣的。 有許多不同的技術術語可以用不同語言命名相同的概念或事物。
那么,你的意思是“回調”或“事件處理程序”?
根據MSDN :回調函數是托管應用程序中的代碼,可幫助非托管DLL函數完成任務。
而且,MADN還向我們介紹了它們之間的區別。 點擊這里
回調是擴展點,允許框架通過委托回調用戶代碼。 這些委托通常通過方法的參數傳遞給框架。
事件是回調的一種特殊情況,它支持提供委托(事件處理程序)的方便且一致的語法。 此外,Visual Studio的語句完成和設計器提供了使用基於事件的API的幫助
此外,在一些書籍中,例如本書 ,作者似乎對MSDN說了同樣的話。
因此,在我看來,你不能說使用回調代替C#中的事件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.