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

来源:https://www.cnblogs.com/u3ddjw/archive/2018/12/31/9920994.html
-Advertisement-
Play Games

1.閑聊 編碼一兩年, 我走過了欄位, 我跑過了類, 卻翻不過方法。(不能靈活使用方法吧) (寫這篇博客全程聽將夜中《永夜》歌曲寫完的,一氣呵成,安利一下) 2.敘事 我們在編碼中,經常搗鼓來搗鼓去的無非就是 “ 欄位,方法 ,類這三種。像欄位,類的使用(引用)很簡單,但是,方法的使用(引用,傳遞) ...


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年最後一天,寫出一篇自己滿意的帖子,儘是自己的理解。

                                                                                                                        


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一.random模塊 隨機 random() 隨機小數 uninform(a,b) 隨機小數 randint(a,b) 隨機整數 choice() 隨機選擇一個 sample() 隨機選擇多個 shuffle() 打亂 二.Counter 計數 三.字典 1.預設值字典 2.有序字典 四.棧和隊列 ...
  • 難點:如何測試。我的解決方式是:a,三種解法,看結果是否一致。b,小數據(100個點),人工排查。第一種方法,暴力法適合小數據。第二種方法:我的改進型。第三種方法:經典方法(分治法)。實驗證明1000萬數據時,我的演算法有優勢。暴力演算法,O(n2)。我的改進型要點:先對所有數據按Y排序。只比較y距離小 ...
  • 此文章非常詳細介紹了Springboot2.0與Mybatis的整合,並且採用Rest風格作為輸入和輸出,項目還使用了兩個很優秀的工具,一個是:Mybatis-Generator代碼生成器,可以方便生成PO、Mapper介面、MapperXml映射文件,而且直接配置生成到項目指定目錄下,不用做任何修... ...
  • 題目內容: 對數字求特征值是常用的編碼演算法,奇偶特征是一種簡單的特征值。對於一個整數,從個位開始對每一位數字編號,個位是1號,十位是2號,以此類推。這個整數在第n位上的數字記作x,如果x和n的奇偶性相同,則記下一個1,否則記下一個0。按照整數的順序把對應位的表示奇偶性的0和1都記錄下來,就形成了一個 ...
  • 0x01 前言 2018年8月22日,Apache Strust2發佈最新安全公告,Apache Struts2存在遠程代碼執行的高危漏洞(S2-057/CVE-2018-11776),該漏洞由Semmle Security Research team的安全研究員Man YueMo發現。該漏洞是由於 ...
  • [TOC] 1. 為什麼要爬蟲? “大數據時代”,數據獲取的方式: 大型企業公司有海量用戶,需要收集數據來提升產品體驗 【百度指數(搜索),阿裡指數(網購),騰訊數據(社交)】 數據管理咨詢公司: 通過數據團隊專門提供大量數據,通過市場調研,問卷調查等 政府/機構提供的公開數據 中華人民共和國統計局 ...
  • 列舉了task-based和value-based兩種拋異常情形的catch方法 ...
  • Visual Studio確實是相當好用,各種簡化操作什麼的簡直不要太舒服。但其容量太大,有時不是很方便,所以今天簡單介紹一下另一個工具--Visual Studio Code. 雖然相比於老大哥Visual Studio,VS Code有很多功能不完善,但它也更靈活輕便。並且VS Code還在不斷 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...