委託與事件
委託
class Program
{
static void Main(string[] args)
{
Publisher publisher = new Publisher("籃球先鋒報");
Observer observerA = new Observer("老A");
publisher.Magazine += observerA.RecvMagazine;
Observer observerB = new Observer("老B");
publisher.Magazine += observerB.RecvMagazine;
publisher.PublishMagezine();
//或者使用下面的方式 區別就是一個在定義的內部觸發,一個在外部觸發
publisher.Magazine?.Invoke(publisher.magazineName);
Console.ReadKey();
}
}
public class Observer
{
private string name;
public Observer(string name)
{
this.name = name;
}
public void RecvMagazine(string message)
{
Console.WriteLine($"{this.name} recv {message}, 仔細讀了一番");
}
}
public class Publisher
{
public string magazineName;
public Publisher(string magazineName)
{
this.magazineName = magazineName;
}
public delegate void MagazineDelegate(string message);
public MagazineDelegate Magazine;
public void PublishMagezine()
{
Magazine?.Invoke(this.magazineName);
}
}
事件
class Program
{
static void Main(string[] args)
{
Publisher publisher = new Publisher("籃球先鋒報");
Observer observerA = new Observer("老A");
publisher.Magazine += observerA.RecvMagazine;
Observer observerB = new Observer("老B");
publisher.Magazine += observerB.RecvMagazine;
publisher.PublishMagezine();
//下面的方式會出現編譯錯誤 只允許在定義的內部觸發,不允許在外部觸發
publisher.Magazine?.Invoke(publisher.magazineName);
Console.ReadKey();
}
}
public class Observer
{
private string name;
public Observer(string name)
{
this.name = name;
}
public void RecvMagazine(string message)
{
Console.WriteLine($"{this.name} recv {message}, 仔細讀了一番");
}
}
public class Publisher
{
public string magazineName;
public Publisher(string magazineName)
{
this.magazineName = magazineName;
}
public delegate void MagazineDelegate(string message);
public event MagazineDelegate Magazine;
public void PublishMagezine()
{
Magazine?.Invoke(this.magazineName);
}
}
經典面試題
貓叫、老鼠跑了,主人醒來了
class Program
{
static void Main(string[] args)
{
Cat cat = new Cat();
Mouse m = new Mouse(cat);
People p = new People(cat);
cat.Scream();
}
}
public class Cat
{
public delegate void ScreamHandler();
public event ScreamHandler OnScream;
public void Scream()
{
Console.WriteLine("貓叫了一聲");
OnScream?.Invoke();
}
}
public class Mouse
{
public Mouse(Cat c)
{
c.OnScream += () => { Console.WriteLine("老鼠跑了"); };
}
}
public class People
{
public People(Cat c)
{
c.OnScream += () => { Console.WriteLine("主人醒來了"); };
}
}
//輸出:
//貓叫了一聲
//老鼠跑了
//主人醒來了
委託與事件的區別
- 事件基於委託,但並非委託 可以把事件看成委託的代理。在使用者看來,只有事件,而沒有委託。
- 事件是對委託的包裝 保護委託欄位,對外不開放。所以外部物件沒法直接操作委託。提供了Add和Remove方法,供外部物件訂閱事件和取消事件。事件的處理方法在物件外部定義,而事件的執行是在物件的內部。至於事件的觸發,何時何地無所謂。
什麼時候使用委託與事件?
如果一個委託不需要再其定義的類之外被觸發,那麼就可以將其轉化為事件,這樣可以保證它不會在外部被隨意觸發。