在我的個人項目中,我從來沒有使用Events.I從來沒有覺得它是必要的。特別是使用Events創建一些問題,限制具有相同參數的方法,這就是爲什麼我沒有使用它。什麼是使用它呢?當時間和我們需要它的地方?爲什麼使用事件?
編輯:使用事件更適用於封閉源代碼庫?因爲我們無法將任何方法附加到現有的封閉源方法,所以事件可以幫助我們解決這個問題?因爲在開放源代碼中,我們可以輕鬆地將我們的方法添加到方法的末尾。
在我的個人項目中,我從來沒有使用Events.I從來沒有覺得它是必要的。特別是使用Events創建一些問題,限制具有相同參數的方法,這就是爲什麼我沒有使用它。什麼是使用它呢?當時間和我們需要它的地方?爲什麼使用事件?
編輯:使用事件更適用於封閉源代碼庫?因爲我們無法將任何方法附加到現有的封閉源方法,所以事件可以幫助我們解決這個問題?因爲在開放源代碼中,我們可以輕鬆地將我們的方法添加到方法的末尾。
那麼,當你需要觀察員到你的對象中發生的:)
最明顯的例子是UI組件的事件做出反應 - 一個Button
暴露按鈕被點擊時被觸發,例如一個事件。
如果你沒有什麼自然而然的感覺就像是暴露事件一樣,那麼不用它們就沒有問題。但是,如果您有任何其他方面對反應感興趣的事情發生在您的對象中,您應該考慮事件 - 和/或Reactive Extensions框架。
您不需要使用它。然而,如果你正在解決的問題需要它,它只是你無論如何最終會做的一個捷徑。但是由於您使用的是具有快捷方式的C#.NET,因此您最好使用它們。它更多的C#是。
事件用於服務器調用客戶端方法時的回調。這樣的選項不僅存在於c#中(f.e.在C++中的函數指針)。因爲你可能不會使用事件來建立你的代碼來避免它們。我會建議更好地瞭解他們,並瞭解他們的優勢。
最明顯的例子是,事件在處理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的問題即可。
哦,我有同樣的問題。我瞭解事件的概念,因爲我在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.Die
和Client.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
類,以便您在生成活動時發送更多信息。
哇......這篇文章很長。我希望你現在得到它。
再說一遍 - 當你想向外部世界通知你的對象的某些特定狀態並適當地處理這個改變時,你可以隨時隨地使用事件。它會讓你的代碼更加靈活並且更容易維護。
良好的迴應,但是你不是在這個例子中有效地使用事件來避免子類播放器? – 2010-06-29 12:02:08
在我的實際代碼中,Player和Npc繼承自GameBeing。 Server-Client示例更好,因爲我必須根據Player類/ Npc對象的不同位置使用這個類。 – rochal 2010-06-29 12:16:09
如果我理解你的例子,請糾正我的錯誤。你在服務器和客戶端使用同一個類,問題在於方法在兩端都做了不同的工作,並且你不能在不修改它的情況下重用相同的類。所以事件有助於克服這個問題,對吧?您可以在任何一方附加Die事件的任何方法。這有助於我們瞭解代碼的可重用性,將代碼分成更多的部分和更靈活的結構。 – Freshblood 2010-06-29 12:21:49
我認爲Button並不是一個好例子。在現代的WPF中,例如,你可以將一個Command綁定到一個按鈕上,這與設置一個單播委託非常相似。 – Den 2013-01-31 17:34:05