2010-06-29 64 views
2

在我的个人项目中,我从来没有使用Events.I从来没有觉得它是必要的。特别是使用Events创建一些问题,限制具有相同参数的方法,这就是为什么我没有使用它。什么是使用它呢?当时间和我们需要它的地方?为什么使用事件?

编辑:使用事件更适用于封闭源代码库?因为我们无法将任何方法附加到现有的封闭源方法,所以事件可以帮助我们解决这个问题?因为在开放源代码中,我们可以轻松地将我们的方法添加到方法的末尾。

回答

1

那么,当你需要观察员到你的对象中发生的:)

最明显的例子是UI组件的事件做出反应 - 一个Button暴露按钮被点击时被触发,例如一个事件。

如果你没有什么自然而然的感觉就像是暴露事件一样,那么不用它们就没有问题。但是,如果您有任何其他方面对反应感兴趣的事情发生在您的对象中,您应该考虑事件 - 和/或Reactive Extensions框架。

+0

我认为Button并不是一个好例子。在现代的WPF中,例如,你可以将一个Command绑定到一个按钮上,这与设置一个单播委托非常相似。 – Den 2013-01-31 17:34:05

1

您不需要使用它。然而,如果你正在解决的问题需要它,它只是你无论如何最终会做的一个捷径。但是由于您使用的是具有快捷方式的C#.NET,因此您最好使用它们。它更多的C#是。

0

事件用于服务器调用客户端方法时的回调。这样的选项不仅存在于c#中(f.e.在C++中的函数指针)。因为你可能不会使用事件来建立你的代码来避免它们。我会建议更好地了解他们,并了解他们的优势。

1

最明显的例子是,事件在处理GUI时特别有用。您的应用程序用户通常会与代码的前端部分(本例中为图形界面)进行交互,而大多数逻辑是“隐藏的”。

我相信你已经看到了这个模式 - 你按下按钮,在后台发生一些事情,你会得到操作结果。您不需要知道发生了什么,您只对应用程序窗口中出现的字符串感兴趣,并说“您的机票已被预订”。

与用户界面相同的故事。在大多数情况下,它不需要知道(也不应该)应用程序逻辑究竟是如何实现的,或者它是做什么的。它在那里呈现结果并与用户互动。

如何在.NET中工作?考虑订票实例的后续部分,一部分说TicketBooker类:

public event Action BookingSuccessful; 

public void BookTicket() 
{ 
    // lot of complex steps that should run in background 
    this.ValidateInputData(); 
    this.GetTicketInfo(); 
    this.CheckUserInfo(); 
    this.SendDataToOperator(); 
    this.WithdrawMoney(); 
    // ...and perhaps lot more stuff you might want to do 
    // in order to book ticket 
    if (booked) 
    { 
     // we're done: let's raise event which will 
     // notify all interested observers 
     this.BookingSuccessful(); 
    } 
} 

正如你所看到的,BookTicket方法可能需要很长时间才能完成,可能有许多复杂的步骤,其中大部分的 - 作为用户 - 我们不不想知道。无论我们是否预订,我们只需要这些信息。

知道了,我们不希望用户因挂机而挂起应用程序等待。用户仍然应该能够与之交互(当然在某种程度上)。因此,用户界面类想要订阅TicketBooker类事件。

TicketBooker tb = new TicketBooker(); 
tb.BookingSuccessful += this.ShowSuccessMessage; 

// ... somewhere here we call tb.BookTicket() method to run in background 
// once it completes (with success), it will raise BookingSuccessful event 
// which will cause ShowSuccessMessage to execute, as we subscribed it 

public void ShowSuccessMessage() 
{ 
    // simply display success message in interface, eg. by setting label text 
} 

entier图片当然比这个简单的例子大得多。事件有助于将应用程序表示层与数据模型/业务逻辑分开,它们处理关于对象变化的感兴趣对象的通知等。

对于初学者来说,你可以在MSDN上查看本教程:Events Tutorial

检查模型 - 视图 - 控制器模式的工作原理可能会提供更好的理解太:MVC

与往常一样,SO在这个主题上充满了资源,只需搜索标签为events & .net的问题即可。

5

哦,我有同样的问题。我了解事件的概念,因为我在JavaScript中大量使用它们,但我无法证明在C#应用程序中使用事件是合理的。我的意思是,我使用服务器OnClick等,但我不明白为什么我会在其他地方使用事件。

其实是有趣的故事,因为当我在研究ORPG游戏的时候,我学到了这一点。考虑下面的代码:

class Player 
{ 
    private int health; 
    public int Health 
    { 
     get 
     { 
      if (health <= 0) 
      { 
       Die(); 
      } 

      return health; 

     } 

     set 
     { 
      health = value; 
     } 
    } 

    public void Die() 
    { 
     // OMG I DIED, Call bunch of other methods: 
     // RemoveFromMap(); 
     // DropEquipment(); etc 
    } 
} 

有道理,对不对?球员没有健康,所以我打电话给Die()。死亡方法然后做任何它应该做的 - 杀死玩家。

当我想在我的ORPG游戏的服务器和客户端应用程序中重用此类时,我的问题就开始了。很容易注意到,Die()方法应该做不同的事情,取决于'Kill'的执行位置 - 在服务器上它应该更新各种不同的数据 - 在客户端上它应该用图形做些事情。

此外 - 如果我想Die()方法做不同的事情,根据播放器的类型呢?所有用户控制的玩家在被杀时与电脑/ AI控制的玩家(NPC)相比应该做不同的事情。

所以,我被迫使用事件:

class Player 
{ 
    public event DieHandler Die; 
    public delegate void DieHandler(Player sender, EventArgs e); 
    public virtual void OnDie(EventArgs e) 
    { 
     if (Die != null) 
      Die(this, e); 
    } 

    private int health; 
    public int Health 
    { 
     get 
     { 
      if (health <= 0) 
      { 
       onDie(new EventArgs()); 
      } 

      return health; 

     } 

     set 
     { 
      health = value; 
     } 
    } 
} 

而现在,当我创建新的播放器,我可以在任何方法分配给它的DieHandler

Player player = new Player("Joe"); 
player.Die += Client.Players.PlayerDie; 

Player npc = new Player("Cookie Monster"); 
npc.Die += Client.Npcs.NpcDie; 

其中Client.Npcs.DieClient.Players.Die是以下之一:

public void NpcDie(Player sender, EventArgs e) 
{ 
    //who hoo, I can be implemented differently 
    //I can even check if sender.Health <= 0 
} 

public void PlayerDie(Player sender, EventArgs e) 
{ 
} 

正如你可以现在看到我们已经灵活地将任何“匹配”方法附加到我们的Die处理程序。我们发送播放器对象作为发送者属性和e中的任何定义的EventArgs。我们可以使用EventArgs发送更多信息,例如 - e.NameOfTheKiller,e.LastHitAtTime等。最好的情况是,您可以定义自己的EventArgs类,以便您在生成活动时发送更多信息。

哇......这篇文章很长。我希望你现在得到它。

再说一遍 - 当你想向外部世界通知你的对象的某些特定状态并适当地处理这个改变时,你可以随时随地使用事件。它会让你的代码更加灵活并且更容易维护。

+0

良好的回应,但是你不是在这个例子中有效地使用事件来避免子类播放器? – 2010-06-29 12:02:08

+0

在我的实际代码中,Player和Npc继承自GameBeing。 Server-Client示例更好,因为我必须根据Player类/ Npc对象的不同位置使用这个类。 – rochal 2010-06-29 12:16:09

+0

如果我理解你的例子,请纠正我的错误。你在服务器和客户端使用同一个类,问题在于方法在两端都做了不同的工作,并且你不能在不修改它的情况下重用相同的类。所以事件有助于克服这个问题,对吧?您可以在任何一方附加Die事件的任何方法。这有助于我们了解代码的可重用性,将代码分成更多的部分和更灵活的结构。 – Freshblood 2010-06-29 12:21:49

相关问题