2015-10-15 39 views
-2
using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace Event_training 
{ 
    class Publisher 
    { 
     public event EventHandler x; 

     public void raise() 
     { 
      x(this, null); 
     } 

    } 

    class Subscriber 
    { 
     public void method1(object o, EventArgs e) 
     { 
      Console.WriteLine("metod1 called"); 
     } 

     public void method2(object o, EventArgs e) 
     { 
      Console.WriteLine("metod2 called"); 
     } 
    } 


    class Program 
    { 
     static void Main(string[] args) 
     { 
      Publisher p = new Publisher(); 
      Subscriber s = new Subscriber(); 

      p.x += s.method1; 
      p.x += s.method2; 

      p.raise(); 
     } 
    } 
} 

難以下傳「this」關鍵字。它是指什麼「x(this,null);」在這裏?我可以使用別的東西而不是「這個」嗎?在這段代碼中,我可以使用別的東西而不是「this」嗎?

+3

請閱讀[此(C#參考)(https://msdn.microsoft.com/en-us/library/dk1507sz.aspx)和關閉問題 –

+0

'this'是指'發佈者'的當前實例。 –

+0

我爲什麼要將它的實例提交給它的方法? – Lyrk

回答

1

爲什麼你需要傳遞的Publisher實例?假設你有幾個出版商和一個用戶:

Publisher p1 = new Publisher() { Name = "Bob" }; 
Publisher p2 = new Publisher() { Name = "Joe" }; 
Subscriber s = new Subscriber(); 

您訂閱x事件都出版商:

p1.x += s.method1; 
p2.x += s.method1; 

現在的問題 - 你怎麼會知道這出版商引發的事件在事件處理?

public void method1(object o, EventArgs e) 
{ 
    Console.WriteLine("metod1 called"); 
} 

這就是爲什麼默認EventHandler委託有兩個參數。第一個通常被稱爲sender而不是o。以便您能夠檢查sender並瞭解哪個發佈商引發了活動。假設Publisher也有Name屬性:

class Publisher 
{ 
    public event EventHandler x; 
    public string Name { get; set; }   

    public void Raise() 
    { 
     EventHandler x = this.x; 
     if (x != null) 
      x(this, EventArgs.Empty); 
    } 
} 

現在,在事件處理程序,你可以得到出版商的名字,因爲你已經通過發行實例(this),甚至處理程序:

public void method1(object sender, EventArgs e) 
{ 
    Publisher publisher = (Publisher)sender; 
    Console.WriteLine(publisher.Name + " raised event x"); 
} 

如果你不這樣做需要傳遞任何事件參數和引發事件的對象實例,然後您可以使用其他類型的委託進行事件。例如。 Action委託沒有任何參數。

class Publisher 
{ 
    public event Action x;  

    public void Raise() 
    { 
     Action x = this.x; 
     if (x != null) 
      x(); // No parameters 
    } 
} 

程序和處理程序將看起來像:

public void method1() 
{ 
    Console.WriteLine("metod1 called"); 
} 
+1

感謝這個詳細的答案。我想我現在明白了。 – Lyrk

+1

@Lyrk good :)正如Dmitry所說,使用'EventHandler'委託是一種標準,它從'WinForms'開發開始。微軟的一些人決定你總是需要知道事件的發送者。並通過所有的'WinForms'系統實現這個'EventHandler'方法。任何事件(按鈕點擊,隱藏/顯示控制等)都是通過EventHandler代表實現的。但是你不受限制,你可以使用你想要的任何代理類型。但我的建議 - 不要混用不同的方法。 –

+0

有時,這些微軟開發人員創建的快捷方式很難讓人們瞭解誰不知道過去的實現。 – Lyrk

1

標準圖案是

// it's not a public method 
internal void raise() 
{ 
    // local copy for being thread safe 
    var localX = x; 

    // do not forget to check for null 
    if (null != localX) 
     localX(this, EventArgs.Empty); // standard EventArgs.Empty, not null 
} 

。注意,this是標準圖案的部分:它示出了其中實例(即this)引發事件。

+0

......或'X?.Invoke(這一點,EventArgs.Empty)'使用C#6 – Dennis

+0

你說的標準模式是什麼意思?你的意思是標準用法? – Lyrk

+0

@Lyrk:*在上下文標準圖案*是一個典型的,建議實行,即https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx –

1

this指的是當前班級的時刻。

例如:

Publisher publisher = new Publisher(); 
publisher.raise(); 

this在這種情況下,publisher實例。也許這是更清楚,如果我給你看: publisher.x(publisher, null);

而且,在你的情況下,第一個參數甚至沒有使用。所以你也可以寫null, null

如您所說,object o通常稱爲sender。這是合理的,因爲無論引發事件的對象是通過此參數傳遞的。

如果您想了解更多關於this關鍵字,請參閱Microsoft網站(link

+0

例如,在上述代碼,我創建了一個名爲「p」的Publisher類的實例。 「this」指的是「p」。這是真的? – Lyrk

+1

'這只是當前的情況。如果在方法中有'this'關鍵字。然後,'this'關鍵字在你的情況下是指'p'。如果你有'發佈者'的多個實例,它們都會引用正確的實例。像:'Publisher p = new Publisher(); Publisher pub = new Publisher();'。 'raise'內的'this'關鍵字等於調用該方法的實例。就像:'做這個''pub''做'pub.raise()'''這個''做'p'raise()' – kevintjuh93

+0

謝謝你的回答。 – Lyrk

相關問題