一眼就能看懂的C#委托、多播委托和事件的區別與聯系。


先說結論

委托:

1.一種可以把函數名當參數傳遞的類型

2.可以通過delegateName()直接觸發

3. 可以賦值。

多播委托:

1可以傳遞多個函數名,調用時會運行多個函數

2.可以通過delegateName()直接觸發

3.可以賦值。

事件:

1.類似多播委托,本質更像是委托的一個實例,但是具有封裝性。

2.不能像委托一樣直接觸發,只能通過事件相關函數觸發。

3.不像委托一樣可以直接賦值,但是可以通過+= 和 -=增加和移除函數。

4.可以實現發布訂閱者模式。

 

委托實例(標粗注意):

我們希望給委托加一個事件,一個中國人問好,並且觸發委托

class Program
    {
        public delegate void SayDelegate(string name); public class ChinesePeople
        {
            public void SayChinese(string name)
            {
                Console.WriteLine("你好" + name);
            }
            public void Greet(string name, SayDelegate action)
            {
               action(name);
            }
        }
        static void Main(string[] args)
        {
            string name = "張三";
            ChinesePeople cp = new ChinesePeople();
       //給委托賦值 SayDelegate delegate1
= cp.SayChinese;
       //只傳一個函數名時,兩種寫法都可以
       delegate1(name); cp.Greet(name,delegate1); cp.Greet(name,cp.SayChinese);
        Console.ReadKey(); } }

結果:

你好張三
你好張三
你好張三


多播委托實例一:

我們希望委托讓一個中國人和一個英國人問好,這時候我們通過+=添加函數。

public delegate void SayDelegate2(string name);
 
    public class ChinesePeople
    {
        public void SayChinese(string name)
        {
            Console.WriteLine("你好" + name);
        }  
    }
    public class EnglishPeople
    { 
        public void SayEnglish(string name)
        {
            Console.WriteLine("hello" + name);
        }
        
    }
   
    class Program
    {
        static void Main(string[] args)
        {
            string name = "張三";
            ChinesePeople cp = new ChinesePeople();
            EnglishPeople ep = new EnglishPeople(); 
            SayDelegate2 delegate1 = cp.SayChinese;
            delegate1 += ep.SayEnglish;
            delegate1(name); 
            Console.ReadLine();
        }
    }

結果:

你好張三
hello張三

 

多播委托實例二:

delegate1(name)看起來太簡潔了,我們根本不知道這個委托是要干什么的, 如果我們跟第一個一樣,把委托封裝到一個方法里調用呢?這樣我們就知道這個委托負責做什么的啦

    public delegate void SayDelegate(string name);

    public class ChinesePeople
    {
        public void SayChinese(string name)
        {
            Console.WriteLine("你好" + name);
        }  
    }
    public class EnglishPeople
    { 
        public void SayEnglish(string name)
        {
            Console.WriteLine("hello" + name);
        }
        
    }
    public class GreetEvent  {
        public void Greet(string name, SayDelegate2 action)
        {
            action(name);
        }
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            string name = "a";
            ChinesePeople cp = new ChinesePeople();
            EnglishPeople ep = new EnglishPeople(); 
            GreetEvent gEvent= new GreetEvent();
            SayDelegate delegate1 = cp.SayChinese;
            delegate1 += ep.SayEnglish;
       //這樣我們就知道這是在“Greet”問好 gEvent.Greet(name, delegate1); Console.ReadLine(); } }

寫完我們發現,wow竟然需要這么多聲明?這完全不符合我們面向對象封裝性的原則呀!我們能不能把委托、事件寫到一起呢?

於是事件(Event)出來了。

 

 

事件實例:

模擬情景:主人來了,主人問好之后,兩個客人——一個中國人一個英國人也向主人問好。

(這就是經典的發布訂閱模式,發布者是主人,訂閱者是中國人和英國人。發布者做出的行動之后,訂閱者也做出相應的行為)

所以我們新建一個主人類,封裝委托,事件,和觸發事件的函數。

  public class Master
    {
        public delegate void SayDelegate(string name);
        public event SayDelegate SayEvent;
        public void Greet(string name)
        {
            if (SayEvent != null)
            {
                SayEvent(name);
            }
        }
    }
    
    public class ChinesePeople
    {
        public void SayChinese(string name)
        {
            Console.WriteLine("你好" + name);
        }  
    }
    public class EnglishPeople
    { 
        public void SayEnglish(string name)
        {
            Console.WriteLine("hello" + name);
        }
        
    } 
    class Program
    {
        static void Main(string[] args)
        {
            string name = "張三";
            ChinesePeople cp = new ChinesePeople();
            EnglishPeople ep = new EnglishPeople(); 
            Master m = new Master();
          
            m.SayEvent += cp.SayChinese;
            m.SayEvent += ep.SayEnglish;
            m.SayEvent -= ep.SayEnglish;
            m.Greet(name);

            Console.ReadLine();
        }
 }

 

注意點:1. 事件不能像委托直接delegate(name)調用,也就是說m.SayEvent()是不可行的。只能通過調用函數去觸發事件

    2.事件不能直接賦值,只能通過+=和-=增加和移除函數

 

突然寫這個文章是因為工作中遇到的需要傳函數名進行封裝的方法~記錄一下,也希望能給初學者帶來幫助。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM