2012-12-30 16 views
3

因此,我正在理解事件和代表。使用特定示例瞭解C#中的代表和事件

我全面理解代表的用法。 關注代表的唯一事情是,是否可以將代理配置爲以任何方式使用與事件無關的函數... 如果是,我該如何編寫代表定義函數的邏輯?(我想這樣的功能其實並沒有多大意義,但知道的很好。)

至於事件......我很難理解它。我知道一個事件是一個函數,當代碼發生某些事情時會被執行。 但是,我沒有得到創建事件的過程。部分。

對於這個問題,我會通過加里·威洛比使用一個答案:https://stackoverflow.com/a/803528/1104766 它被張貼在從中我試圖瞭解這整個主題相關的問題。

我沒有在上面的例子中得到什麼:
MyObject.OnMaximum += new MyEventHandler(MaximumReached);
首先,你怎麼能創建委託的實例,而當它需要通過2只1變量?必須有我丟失的東西...
關於此行的第二件事情是,new ...()實例是添加OnMaximum功能駐留在MyObject這是MyClass一個實例 - 究竟是OnMaximum如果這樣的事情可以做到?它從來沒有真正定義過!

 if(OnMaximum != null) { 
     OnMaximum(this, new MyEventArgs("You've entered " + 
      value.ToString() + 
      ", but the maximum is " + 
      Maximum.ToString())); 
     } 

至於這一部分,OnMaximum的調用,但它的邏輯從來沒有真正在代碼的任何地方定義的,所以可能是什麼結果?很明顯,我猜這是文本「你輸入了.............」,但我的問題是更具體的,真正發生的值與函數/事件收到?

爲了清楚起見,我在BOLD中標記了所有的問題。

上海,我知道這個問題一般已經發布了幾次。
請注意,這個具體的問題是指由另一個成員寫的答案,這裏提出的問題是特定於這個例子。這就是爲什麼這些答案不能在谷歌中找到。
儘管我記錄之前做過搜索,但我確實試圖理解,但我認爲例子是理解某些東西的最佳方式,特別是當我對英語CS詞彙缺乏知識時。

回答

7

我認爲你可能會患上過量的語法糖!

你看,所有的事件是,是一個代表。其實,說實話,這是一個代表,可能是null的集合。

讓我們舉個例子:

public class Alarm 
{ 
    public delegate void AlarmEvent(); 

    // my secret stuff 

    // raise it! 
    public void Ring() 
    { 
     if(OnAlert != null) 
      OnAlert(); 
    } 

    public event AlarmEvent OnAlert; 
} 

所有事件關鍵字給了我們這裏,是添加和刪除監聽到該事件的能力......

Alarm a = new Alarm(); 
a.OnAlert += myevent; 
a.OnAlert += myotherevent; 

另一位代表手,雖然工作完全像我們剛剛描述的那樣,但更類似於函數指針。想象一下抽象渲染器,我可以這樣創建類:

public abstract class Renderer 
{ 
    protected abstract void RenderImpl(); 
} 

這意味着,我必然會從渲染中派生出來。但是如果這個渲染器拿了一個代表呢?

public abstract class Renderer 
{ 
    public delegate void RenderDelegate(); 

    public Renderer(RenderDelegate) { /* ... */ } 
} 

我們現在分離出構圖。

我在做什麼?好不好?就事件而言,我讓公衆成爲我班的觀察員。他們可以反應。在第二種情況下,我定義了一個用戶提供的委託來執行利基函數,而我保留了大部分控制權。

代表和事件大多是同一件事 - 但它是我們確定哪一個是合適的設計選擇。

爲了解決您的其他問題,您提出了一個事件與代表的很好的例子。如果我們要更改上面的警報類別,以允許代表返回truefalse,那麼會發生什麼情況?

我們會得到幾個觀察者返回true,但誰是對的,以及如何檢查他們?

沿着單個委託路線,但是......「呈現成功」或「呈現失敗」。改變這個單一的委託並不是一個問題。我們可以預測測試我們的渲染器是否完成了這項工作:

if(!delegate_->Invoke()) 
    fallBackCode(); 

我們無法真正做到這一點與事件。好吧,不可預測。

簡而言之,當您想要廣播某些內容並讓其他人在收到該事件時做某些事情時,事件就在那裏。炸彈爆炸了...跑開,躲起來,給國民警衛隊打電話,關掉烤箱,或者蹲下並蓋上蓋子。

代表允許您在不更改模型的情況下更改您的功能(代表遵循簽名!)。代表的一個很好的例子是當你撥打List<T>.Sort。這是一個代表。它有一個簽名。

但是,您也可以將它們用於更高級的事情,例如更改Renderer類而不訴諸接口,並且能夠提供用戶定義的「片段」。我猜這裏最簡單的比喻是Win32中的所有者繪製控件。無需重寫整個類,不需要提供接口並編寫大量代碼。只需更改呈現組合框中項目的位。代表是你如何實現這一目標的絕佳例子。

+0

+1這個解釋.. – ridoy

+0

所以你的'myevent'和'myotherevent'等於我鏈接到的問題中聲明的'MaximumReached'函數/監聽器?這是否意味着當一個事件被調用像'someHandler(int num)'時,它會觸發它的所有偵聽器並將它們傳遞給可用的變量?這也意味着,所有分配給處理程序的監聽器都會收到/返回相同類型/數量的變量,對吧?有道理 - 謝謝!但是,我仍然不完全理解你的最後一個例子......如果你能夠提供一個有/無委託的例子(即使是理論方法),它也能真正幫助我。 – Asaf

+0

@xTCx,我已經擴展了我的答案。希望它有助於:) –

0
class Program 
    { 
     static void Main(string[] args) 
     { 
      Parent p = new Parent(); 
     } 
    } 

    //////////////////////////////////////////// 

    public delegate void DelegateName(string data); 

    class Child 
    { 
     public event DelegateName delegateName; 

     public void call() 
     { 
      delegateName("Narottam"); 
     } 
    } 

    /////////////////////////////////////////// 

    class Parent 
    { 
     public Parent() 
     { 
      Child c = new Child(); 
      c.delegateName += new DelegateName(print); 
      //or like this 
      //c.delegateName += print; 
      c.call(); 
     } 

     public void print(string name) 
     { 
      Console.WriteLine("yes we got the name : " + name); 
     } 
    } 
0

加油夥計們!你們所有人都成功複雜了代表:)!

我會盡量在這裏留下一個提示:我瞭解委託,一旦我意識到jquery ajax調用Javascript。例如:ajax.send(url,data,successcallback,failcallback)是函數的簽名。如你所知,它將數據發送到服務器URL,作爲響應,它可能是200OK或其他一些錯誤。如果發生此類事件(成功/失敗),您需要執行一項功能。所以,這就像一個函數的佔位符,能夠提及成功或失敗。 該佔位符可能不是非常通用的 - 它可能會接受一組參數,並且可能不會返回值。這種佔位符的聲明,如果在C#中完成,則被稱爲代表!由於javascript函數對參數數量不嚴格,您只會將它們看作GENERIC佔位符......但C#有一些STRICT聲明......歸結爲DELEGATE聲明!

希望它有幫助!

+0

你是什麼意思由GENERIC佔位符。我失去了那裏 –

+0

我的意思是,GENERIC佔位符作爲函數佔位符;你可以定義任何函數,比如定義了ajax.send的頁面/組件之外的ExtFunct1(),當實際調用ajax.send時,將函數名稱「ExtFunct1」成功或失敗回調參數place [placeholder],那在運行時被調用。 – HydTechie