2015-10-15 64 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

相关问题