簡體   English   中英

何時使用回調代替c#中的事件?

[英]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表達式時,我會使用FuncAction

事件可以多次注冊,有時是理想的。 如果你想要多個回調,那么必須為回調實現一個注冊系統。

一個例子是回調應該返回一些東西。 例如(愚蠢的例子):

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM