C# 通俗說 委托(和事件)


1.閑聊

  編碼一兩年,

  我走過了字段,

  我跑過了類,

  卻翻不過方法。(不能靈活使用方法吧)

  (寫這篇博客全程聽將夜中《永夜》歌曲寫完的,一氣呵成,安利一下)

2.敘事

  我們在編碼中,經常搗鼓來搗鼓去的無非就是 “ 字段,方法 ,類這三種。像字段,類的使用(引用)很簡單,但是,方法的使用(引用,傳遞)貌似,有點“模糊”不清。甚至有些初學害怕委托,害怕見到delegate這個關鍵字。

但是一般稍微成熟點的大佬的方法都是充滿delegate的,是不是,哈哈哈。因此,你不得不去使用。關於方法引用的好處嘛,一句話,逼格很高,你必須學會去使用,這是上升為中級程序員必須會的。(代碼可讀性,耦合性等好處大大有)

  那么,現在如果讓我來設計如何傳遞(引用)方法,我是如何設計的。

3.如何設計傳遞(引用)方法

  1)方法大概是什么樣

     大概就是可以有/無返回參數,有傳入參數,傳入參數數量不一定,類型不一定。

即如圖

  

  2)明確方法定義

      因為如上圖可知,方法類型是很不明確的,那么我們需要明確好方法。這里用TOM(type of method)關鍵字作為我們明確方法類型的關鍵字。 

     public TOM void tom1();//tom1是無返回值,無傳入參數的方法類型
        public TOM void tom2(string str);//tom2是i無返回值,有一個string類型參數
        public TOM int tom3(int num, string str);//tom3是int型返回值,有一個int傳入參數+一個string型傳入參數

 我們用這樣的規則(這個規則,是需要死記),就可以明確定義出任意我們 想要的具體方法類型。(這應該很容易理解的吧)

  3)使用方法類型

   由上述2可知,有三種例子類型。很簡單

      public TOM void tom1();//tom1是無返回值,無傳入參數的方法類型
        public TOM void tom2(string str);//tom2是i無返回值,有一個string類型參數
        public TOM int tom3(int num, string str);//tom3是int型返回值,有一個int傳入參數+一個string型傳入參數
      

        static void Main(string[] args)
        {
            tom1 t1 = Test1;
            t1();

            tom2 t2 = Test2;
            tom2 t2_2 = Test2_2;
            t2("tttt22222");
            t2_2("tttt22222");

            tom3 t3 = Test3;
            int num3 = t3(1, "3333tt");
            Console.Read();
        }

       static  void Test1()
        {
            Console.WriteLine("test1");   
        }

        static void Test2(string str)
       {
           Console.WriteLine("test2:"+str);
       }


        static void Test2_2(string str)
        {
            Console.WriteLine("test_2:"+str);
        }
        static int Test3(int num,string str)
        {
            Console.WriteLine("THis is Test3:"+num.ToString()+str);
            return num + 1;
        }

(上述TOM 改為delegate ,即可編譯成功,真的吐槽為何中文翻譯為委托,真的很拗口,不過,真的很不好定義吧....我也想不到更好的兩個字可以概括的)

4.回歸官方說委托

  上述TOM即為委托(delegate),為啥我不直接說delegate,直接說delegate,這個東西,真的很難理解。記住,TOM(type of method),方法的類型,再准確的說是定義方法的類型的類型。TOM tom1,這個tom1,則為某具體方法的類型的類型。

接下來用delegate來寫吧,但是你內心還是要記住type of method(方法的類型)。

(其實官方講,我是沒啥好講的,直接推薦兩篇博客吧 https://www.cnblogs.com/hushzhang/p/5901052.html)

5.實例應用

        因為最近自己墮入愛河,舉個談戀愛的例子吧。

  1)男女戀愛分手用例。

    需求:女孩紙開心值降低到一定,就會提出分手。或者男孩紙比較渣,男孩紙提出分手。提出分手,

女孩紙會哭泣;男孩紙會變為單身狗。

    步驟:

       ①首先,先定義一個無返回值,無傳入參數的委托,SeparateDelegate。  

          public delegate void SeparateDelegate(); 

       ②聲明一個女孩紙類,聲明一個SeparateDelegate委托的實例mSeparateDel,並在初始化中給mSeparateDel

賦初始(注冊)分手回調;女孩紙開心值低於1的時候,觸發分手。(女孩紙被動分手,不開心才會分手,因為女孩紙不開心才會分手嘛。)      

 class GirlFriend
    {
        public SeparateDelegate mSeparateDel;
        public string mName { get; set; }
        private int happyNum;
        public int mHappyNum {
            get
            {
                return happyNum;
            }

            set
            {
                happyNum = value;
                if(happyNum<1)
                {
                    Console.WriteLine("我女孩紙,決定了,分手,開始觸發分手:");
                    mSeparateDel();
                }
            }
        }

        public GirlFriend(string name)
        {
            mName = name;
            mHappyNum = 80; //剛開始做女朋友肯定很開心嘛
            mSeparateDel = SeparateCallBack;
        }


        void SeparateCallBack()
        {
            Console.WriteLine("我是女孩子,分手了,我大哭...");
        }
    }

        ③聲明一個男孩紙類,可以將女孩紙設為男孩紙女朋友,並繼續注冊女孩紙提出分手可觸發的回調;男孩紙可以提出分手。(渣男就是

不一樣,分手無理由,各種理由,花心啊,膩了,遇到更漂亮的小姐姐等等,跟開不開心無關系,哈哈哈...)

 class BoyFriend
    {
        public string name { get; private set; }
        public GirlFriend mGirlFriend;
        public BoyFriend(string name,GirlFriend girl)
        {
            this.name = name;
            this.mGirlFriend = girl;
            girl.mSeparateDel += RemoveGirlFriend;
        }

        void RemoveGirlFriend()
        {
            if (this.mGirlFriend != null)
            {
                this.mGirlFriend = null;
            }
            Console.WriteLine("作為男孩紙,很難受,男人不哭,回歸單身狗");
        }

        public void PresentSeparate()
        {
            this.mGirlFriend.mSeparateDel();
        }
    }    

      ④實際運行。(保證代碼可以跑起來)  

 class Program
    {
        static void Main(string[] args)
        {
            GirlFriend gl = new GirlFriend("XiaoHong Li"); //當然先有女朋友
            BoyFriend mySelf = new BoyFriend("Jack Deng",gl);//才有男朋友
            gl.mHappyNum = 0;//開心值降低,女孩紙自身觸發分手
         //   mySelf.PresentSeparate(); //男孩紙主動觸發分手
            Console.Read();
        }
    }

  可以看到上述女孩紙自身調用和男孩紙調用出發都可以調用以下運行結果(紅框中的,分手可以觸發的回調)。

       

6.委托與事件的區別

  還是繼續上述用例來說,因為上述用例,觸發分手,男孩子和女孩紙都可以觸發分手。

  需求:現在因為當今社會是女權主義偏多了,再加上程序員們的忠貞,保證不會觸發分手,現在就是要求,設計如此:男孩紙不能觸發分手,

只能由女孩紙觸發。該怎么做哦。

  分析:

     因為女生的委托實例 mSeparateDel是public的,當然是渣男想調就能調,甚至誰想調,任何時候都能調。那我們把public改為private。

可是矛盾來了,男孩紙也不能注冊分手回調了(導致的問題是女孩說分手,男孩不知道,沒影響),這樣做肯定是不行的。

  解決:

    這時候,事件出來了。為了解決上述問題,只要

    //  public  SeparateDelegate mSeparateDel;
        public event  SeparateDelegate mSeparateDel;

    改成這樣,就行了,增加event關鍵字。就是事件了。

  結果:

    

  編譯報錯了。渣男不能調用了,但是還是可以+=,注冊,是沒有問題的。(事件的作用及區別)

  我的理解是,事件與委托的區別:

    事件是一種特殊的委托,事件∈委托,委托∉事件,即事件是委托的子集。

    事件是對委托的一種封裝,類似於屬性是對字段的封裝。

  總結:事件就是巧妙的讓渣男不再說分手。強化女權,只能讓女子說分手,而又能影響到男子。

7.感悟

    說來慚愧,筆者現在三年Unity經驗,對於委托事件的理解,也是最近才算完全參透的吧。之前真的是看過無數篇文章,一直都是含糊不清,也看了網上

很多關於委托事件的博客,一直真的是,越來越不模糊吧,直至現在,我想,我這一次,真的應該是徹底理解了。(如有不合,歡迎指正。)這其中,盡是自己的

理解,如題所述,通俗說,沒有太多的官話。

    2018年12月31日完,終於趕在2018年最后一天,寫出一篇自己滿意的帖子,盡是自己的理解。

                                                                                                                        


免責聲明!

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



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