C#的事件基於委托,所以先說委托。
一切脫離實際場景的抽象概念新手看上去就像是在扯犢子,不錯,我就是個新手。所以我需要一個實際的場景。
明天剛好考試(商務英語),考試上有兩個角色(class):老師(Teacher)和學生(Student),在考試時間終止的時候,老師會觸發(invoke)一個事件(event):“考試時間到了,我tm要收卷子了!”(OnTestTimeUp),而每個學生都要訂閱這個事件,並在這個事件發生的時候上交試卷(HandInTestPaper)。如果不用事件的話,老師在時間結束的時候就要調用每個學生的的HandInTestPaper方法,如果使用事件,只要在學生被實例化的時候在事件上增加一個訂閱即可。
1、老師和學生之間的橋梁
老師和學生之間的橋梁用委托來完成,這裡就用最簡單的一種委托:沒有返回、沒有參數、不支持泛型:
public delegate void TestTimeUpHandler();
接著,用這個委托定義一個事件,這樣學生就可以訂閱這個事件
public event TestTimeUpHandler TestTimeUp;
學生訂閱事件後,當老師觸發這個事件的時候,學生就會做出一些響應
public void OnTestTimeUp() { TestTimeUp?.Invoke(); }
2、學生如何訂閱?
首先回到剛才的委托,這個委托非常簡單,沒有返回、沒有參數,所以學生類中只要有一個方法,簽名與這個一致就可以訂閱這個事件:
public void HandInTestPaper() { Console.WriteLine("The test paper has been handed in."); }
然後在實例化後直接將這個方法訂閱給事件即可
3、兩邊的關系
4、完整的例子
Delegate
/// <summary> /// 委托,考試時間到的Handler /// </summary> public delegate void TestTimeUpHander();
Teacher
/// <summary> /// 教師類 /// </summary> public class Teacher { public event TestTimeUpHander TestTimeUp; public void OnTestTimeUp() { TestTimeUp?.Invoke(); } }
Student
/// <summary> /// 學生類 /// </summary> public class Student { public string Name { get; private set; } public Student(string name) { this.Name = name; } public void HandInTestPaper() { Console.WriteLine($"{this.Name}\' paper has been handed in"); } }
5、具體場景實現
public class Program { public static void Main() { Teacher teacher = new Teacher(); var tom = new Student("Tom"); var jerry = new Student("Jerry"); var spark = new Student("Spark"); var tyke = new Student("Tyke"); // 訂閱teacher的TestTimeUp事件 teacher.TestTimeUp += tom.HandInTestPaper; teacher.TestTimeUp += jerry.HandInTestPaper; // invoke TestTimeUp 事件 teacher.OnTestTimeUp(); Console.WriteLine(); teacher.TestTimeUp -= tom.HandInTestPaper; teacher.TestTimeUp += tyke.HandInTestPaper;
teacher.OnTestTimeUp(); Console.ReadKey(); } }
運行的結果如下:
可以看到,第一次觸發事件的時候,只有Tom和Jerry兩個訂閱了事件的實例執行了HandInTestPaper方法,第二次觸發事件前,移除了Tom的訂閱,同時增加了Tyke的訂閱,所以Jerry和Tyke執行了HandInTestPaper方法。
以上,是最簡單的C#委托與事件的實現,復雜的方法日後再說