5.事件
C#提供了對事件的直接支持。盡管事件處理一直是編程的基本部分,但令人驚訝的是,大多數語言在正式化這個概念上所做的努力都微乎其微。如果看看現今主流框架是如何處理事件的,我們可以舉出如下例子:Delphi的函數指針(稱為閉包)和Java的內部類適配器,當然還有Windows API消息系統。C#使用delegate和event關鍵字提供了一個清爽的事件處理方案。我認為描述這個機制的最好的辦法是舉個例子來說明聲明、觸發和處理事件的過程:
// 委托聲明定義了可被調用的方法簽名【譯注:這裡的簽名可以理解為“原型”】
public delegate void ScoreChangeEventHandler (int newScore, ref bool cancel);
// 產生事件的類
public class Game
{
file://注意使用關鍵字
public event ScoreChangeEventHandler ScoreChange;
int score;
// 屬性Score
public int Score
{
get
{
return score;
}
set
{
if (score != value)
{
bool cancel = false;
ScoreChange (value, ref cancel);
if (! cancel)
score = value;
}
}
}
}
// 處理事件的類
public class Referee
{
public Referee (Game game)
{
// 監視game中的score的分數改變
game.ScoreChange += new ScoreChangeEventHandler (game_ScoreChange);
}
// 注意這個方法簽名和ScoreChangeEventHandler的方法簽名要匹配
private void game_ScoreChange (int newScore, ref bool cancel)
{
if (newScore < 100)
System.Console.WriteLine ("Good Score");
else
{
cancel = true;
System.Console.WriteLine ("No Score can be that high!");
}
}
}
file://測試類
public class GameTest
{
public static void Main ()
{
Game game = new Game ();
Referee referee = new Referee (game);
game.Score = 70;//【譯注:輸出 Good Score】
game.Score = 110;// 【譯注:輸出 No Score can be that high!】
}
}
在GameTest裡,我們分別創建了一個game和一個監視game的referee,然後,然後我們改變game的Score去看看referee對此有何反應。在這個系統裡,game沒有referee的任何知識,任何類都可以監聽並對game的score變化產生反應。關鍵字event隱藏了除了+=和-=之外的所有委托方法。這兩個操作符允許你添加(或移去)處理該事件的多個事件處理器。