最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#中的委托和事件詳解

 更新時(shí)間:2022年07月07日 10:50:20   作者:社會(huì)主義接班人  
本文詳細(xì)講解了C#中的委托和事件,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

從大學(xué)就開始做C#這塊,也做C#幾年了,最近又從ios轉(zhuǎn)回.Net,繼續(xù)做C#,之前也沒(méi)有寫博客的習(xí)慣,寫博客也是從我做ios的時(shí)候開始的,現(xiàn)在既然又做回了.net,那就寫點(diǎn)關(guān)于.Net的博客,可能在大牛眼里這些都是簡(jiǎn)單基礎(chǔ)的,不過(guò)回過(guò)頭看我當(dāng)時(shí)初學(xué)的時(shí)候覺(jué)得委托事件是不容易理解的,我這里也是想著聯(lián)系著OC,兩者有比較的學(xué)習(xí)下。畢竟都是面向?qū)ο笳Z(yǔ)言,思想是相通的。

委托在OC中類似block,都是指向一個(gè)函數(shù),其實(shí)他沒(méi)和C++的函數(shù)指針類似。但委托還是和函數(shù)指針不太一樣,委托是完全面向?qū)ο蟮?,是類型安全可靠的。C++的指針僅僅指向成員函數(shù),而委托同時(shí)封裝了一個(gè)對(duì)象實(shí)例和方法。

委托聲明用于定義一個(gè)從System.Delegate類派生的類。

格式:屬性集 修飾符 delegate 返回值類型(A) 標(biāo)識(shí)符(C)(形參列表(B));

一、委托是什么?

看上面的紅字我們可以明白其實(shí)委托是一個(gè)類。其實(shí)類是什么?類也是一種數(shù)據(jù)類型,它了String類一樣,也是一個(gè)數(shù)據(jù)類型,所以呢委托其實(shí)也是一個(gè)數(shù)據(jù)類型,只是這個(gè)數(shù)據(jù)類型和其他的有點(diǎn)不同,它這個(gè)數(shù)據(jù)類型指向的是一個(gè)函數(shù)。一個(gè)返回值為A,形參列表為B的名為標(biāo)識(shí)符C的函數(shù)。其實(shí)這和OC中的block類似,block中也是用來(lái)定義函數(shù)。我們用typedef void(^myblock1)(int a,int b);來(lái)定義一個(gè)block,其實(shí)就是定義一個(gè)數(shù)據(jù)類型。上面的委托聲明也是定義了一個(gè)引用類型的數(shù)據(jù)類型。

二、委托怎么用?

上面也說(shuō)了,聲明一個(gè)委托其實(shí)就是聲明了一個(gè)數(shù)據(jù)類型,和Person、String一樣都是一個(gè)數(shù)據(jù)類型。我們?cè)谑褂梦泻褪褂肞erson、String類型的數(shù)據(jù)一樣。也是先聲明:public 類型(Person、String) 變量(或?qū)傩?名。所以我們?cè)谑褂梦袝r(shí)也是這樣。只是這個(gè)變量或?qū)傩詫?duì)應(yīng)的是一個(gè)函數(shù)。

三、例子

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Delegate
{
    //定義了一個(gè)從System.Delegate類派生的類
    //也可以理解為一種數(shù)據(jù)類型 這種數(shù)據(jù)類型指向返回值為void 參數(shù)為Person對(duì)象的函數(shù)
    //我們也可以把Person類理解為一種數(shù)據(jù)類型 只是它包含的是Name和Age
    public delegate void EatFood(Person p);

    public class Person
    {
    
        public string Name { get; set; }

        public int Age { get; set; }

        public Person(string name, int age)
        {
            Name = name;
            Age = age;
        }

        //既然委托是一數(shù)據(jù)類型和String一樣,所以可以像聲明String對(duì)象一樣聲明代理變量
        public EatFood eatFood;

        public void eating()
        {
            if (eatFood != null)
            {
                eatFood(this);
            }
        }

    }
}

上面定義了一個(gè)Person類,也定義了一個(gè)定義了一個(gè)從System.Delegate類派生的類EatFood,同時(shí)在Person類中聲明了EatFood類類型的一個(gè)變量,在eating()函數(shù)中使用了這個(gè)變量。ps:請(qǐng)留意上面代碼中的注釋。下面的代碼中我們定義了兩個(gè)Person對(duì)象,一個(gè)chinesePerson一個(gè)englishPerson,而分別為兩個(gè)類的eatFood變量指定不同的函數(shù)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Delegate
{
    class Program
    {
        static void Main(string[] args)
        {
            Person chinesePerson = new Person("小明",25);
            //通過(guò)構(gòu)造函數(shù)實(shí)例化對(duì)象
            chinesePerson.eatFood = new EatFood(chineseEat);
            chinesePerson.eating();

            Console.WriteLine("--------------------------------------");

            Person englishPerson = new Person("Ivan",25);
            //通過(guò)直接復(fù)制來(lái)實(shí)例化對(duì)象
            englishPerson.eatFood = englishEat;
            englishPerson.eating();
            Console.ReadLine();
             
        }
        static void chineseEat(Person p)
        {
            Console.WriteLine("我是{0},我今年{1}歲了,我吃饅頭",p.Name,p.Age);
        }
        static void englishEat(Person p)
        {
            Console.WriteLine("I'm {0},I am {1} , I eat MianBao",p.Name,p.Age);
        }
    }
}

可以看到針對(duì)不同的對(duì)象指定不同的eatFood變量則執(zhí)行的結(jié)果也不一樣。

四、委托和其他數(shù)據(jù)類型的區(qū)別

上面也說(shuō)了可以把委托當(dāng)做是一個(gè)數(shù)據(jù)類型,但它和普通的數(shù)據(jù)類型還是有區(qū)別的。這可能就是現(xiàn)在的個(gè)性吧,委托也有委托的個(gè)性。

委托實(shí)例化用于創(chuàng)建委托實(shí)例,和類實(shí)例創(chuàng)建語(yǔ)法相同。但委托可以封裝多個(gè)方法,這些方法的集合合稱為調(diào)用列表。委托使用+、+=、-、-=運(yùn)算符向調(diào)用列表中增加或刪除方法。

我們對(duì)上面的代碼稍作改動(dòng),Person類不用改,只改Main方法中的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Delegate
{
    class Program
    {
        static void Main(string[] args)
        {
            Person chinesePerson = new Person("小明",25);
            //通過(guò)構(gòu)造函數(shù)實(shí)例化對(duì)象
            chinesePerson.eatFood = new EatFood(chineseEat);
            chinesePerson.eatFood += englishEat;
            chinesePerson.eating();

            Console.WriteLine("--------------------------------------");

            Person englishPerson = new Person("Ivan",25);
            //通過(guò)直接復(fù)制來(lái)實(shí)例化對(duì)象
            englishPerson.eatFood = englishEat;
            englishPerson.eatFood += chineseEat;
            englishPerson.eating();
            Console.ReadLine();
             
        }
        static void chineseEat(Person p)
        {
            Console.WriteLine("我是{0},我今年{1}歲了,我吃饅頭",p.Name,p.Age);
        }
        static void englishEat(Person p)
        {
            Console.WriteLine("I'm {0},I am {1} , I eat MianBao",p.Name,p.Age);
        }
    }
}

為了促進(jìn)中西交流,好多人去留學(xué)也有好多來(lái)到中國(guó)的,所以在吃的方面彼此都會(huì)吃對(duì)方的。所以要增加方法來(lái)表示吃不同的食物。有了委托可以通過(guò)+=、-=來(lái)實(shí)現(xiàn)增加、刪除調(diào)用列表,這樣就方面很多。從下面的輸出結(jié)果能看到,每個(gè)Person對(duì)象都調(diào)用了chineseEat、englishEat函數(shù)。

五、好處

上面的demo也展示了委托的使用方法,通過(guò)上面的使用我們可以思考下使用它的好處。我們?nèi)绻皇褂梦衼?lái)實(shí)現(xiàn)這個(gè)功能的話,我們可能會(huì)在Person類中做一個(gè)判斷,判斷下是Chinses還是English,可是這樣的話,如果哪天有了日本、法國(guó)等,那又要多好多個(gè)判斷。可擴(kuò)展性不好。可能有的會(huì)說(shuō)可以在Person里面定義一個(gè)虛方法,分別聲明Chinese、English類繼承Person類重寫虛方法,這確實(shí)是一個(gè)方法,如果有新的要擴(kuò)展的話可以直接創(chuàng)建一個(gè)新的類重寫虛方法就搞定了,不過(guò)這樣的話如果只是這個(gè)方法不同,就要寫一個(gè)類,這樣未免殺雞用牛刀了。所以說(shuō)委托還是一個(gè)不錯(cuò)的選擇。如果不僅要增加語(yǔ)言還要增加方法那這就更麻煩了。有了委托這些全解決。

六、事件

對(duì)象之間的交互是通過(guò)消息傳遞來(lái)實(shí)現(xiàn)的,而事件就是對(duì)象發(fā)送的消息,通過(guò)發(fā)信號(hào)的形式通知操作的發(fā)生。引發(fā)事件的對(duì)象為事件發(fā)送方,捕獲事件并對(duì)其做出響應(yīng)的對(duì)象為事件接收方。在事件通信中,事件發(fā)送方不知哪個(gè)對(duì)象或方法將接收它引發(fā)的事件,所需要的是在發(fā)送方和接收方之間用一個(gè)紐帶來(lái)聯(lián)系,在C#中使用委托為這個(gè)紐帶。

事件聲明的格式:屬性集 修飾符 event 委托類型 事件名。

其實(shí)說(shuō)白了就是事件是對(duì)委托變量的封裝。請(qǐng)注意上面寫的,我一直寫的是委托類型的變量,面向?qū)ο蟮娜筇卣髦痪褪欠庋b,例如變量和屬性。在上面直接使用委托來(lái)指定函數(shù),其實(shí)這和直接使用變量一樣,但是在面向?qū)ο笾幸话悴粫?huì)直接訪問(wèn)變量,而是對(duì)變量進(jìn)行封裝,例如屬性{get;set;}方法。事件是對(duì)委托的封裝。我們來(lái)看一下事件的使用,和上面使用委托一樣,我們?cè)赑erson類中聲明一個(gè)事件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Delegate
{
    //定義了一個(gè)從System.Delegate類派生的類
    //也可以理解為一種數(shù)據(jù)類型 這種數(shù)據(jù)類型指向返回值為void 參數(shù)為Person對(duì)象的函數(shù)
    //我們也可以把Person類理解為一種數(shù)據(jù)類型 只是它包含的是Name和Age
    public delegate void EatFoodDelegate(Person p);

    public class Person
    {
    
        public string Name { get; set; }

        public int Age { get; set; }

        public Person(string name, int age)
        {
            Name = name;
            Age = age;
        }

        //既然委托是一數(shù)據(jù)類型和String一樣,所以可以像聲明String對(duì)象一樣聲明代理變量
        //public EatFood eatFood;
        //之前是直接聲明委托,現(xiàn)在是聲明一個(gè)事件
        public event EatFoodDelegate EatFoodEventHandler;

        public void eating()
        {
            
            if (EatFoodEventHandler != null)
            {
                EatFoodEventHandler(this);
            }
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Delegate
{
    class Program
    {
        static void Main(string[] args)
        {
            Person chinesePerson = new Person("小明",25);
            //通過(guò)構(gòu)造函數(shù)實(shí)例化對(duì)象
            chinesePerson.EatFoodEventHandler += new EatFoodDelegate(chineseEat);
            chinesePerson.EatFoodEventHandler += englishEat;
            chinesePerson.eating();

            Console.WriteLine("--------------------------------------");

            Person englishPerson = new Person("Ivan", 25);
            //在委托中 可以直接使用=來(lái)給委托對(duì)象復(fù)制 而在事件中就不能直接使用= 要使用+=
            englishPerson.EatFoodEventHandler += new EatFoodDelegate(englishEat);
            englishPerson.EatFoodEventHandler += chineseEat;
            englishPerson.eating();
            Console.ReadLine();

        }
        static void chineseEat(Person p)
        {
            Console.WriteLine("我是{0},我今年{1}歲了,我吃饅頭",p.Name,p.Age);
        }
        static void englishEat(Person p)
        {
            Console.WriteLine("I'm {0},I am {1} , I eat MianBao",p.Name,p.Age);
        }
    }
}

上面可以看到,使用事件來(lái)實(shí)現(xiàn)了同樣的功能。

七、委托和代理設(shè)計(jì)模式的區(qū)別

不管是使用委托或者事件其實(shí)它們都是在A對(duì)象(本例中的Person對(duì)象)中調(diào)用B對(duì)象中的方法,這與設(shè)計(jì)模式中有相似之處。具體代理設(shè)計(jì)模式這里就省略了,委托和代理都是在A對(duì)象使用B對(duì)象中的方法。不過(guò)它們還是有區(qū)別的,委托中在A中直接使用的是B中的方法,是類與方法之間的,代理設(shè)計(jì)模式中是將A類中設(shè)置一個(gè)B類變量,然后通過(guò)B來(lái)使用B中的方法,是類與類之間的。這也是我的個(gè)人理解,不知道對(duì)不對(duì),錯(cuò)了的話也希望大牛指正,以免耽誤了其他的社會(huì)主義接班人。

到此這篇關(guān)于C#委托和事件的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評(píng)論

津南区| 井冈山市| 黄梅县| 定襄县| 永宁县| 蕉岭县| 双桥区| 镇巴县| 康平县| 桃江县| 新源县| 阿鲁科尔沁旗| 汝阳县| 绥芬河市| 资中县| 农安县| 奉新县| 中江县| 陇川县| 晋城| 蚌埠市| 许昌市| 额尔古纳市| 邯郸市| 宝丰县| 潮州市| 康马县| 西乌| 曲周县| 武邑县| 星座| 杂多县| 鹤庆县| 丁青县| 贵州省| 亚东县| 蕉岭县| 弋阳县| 土默特右旗| 饶阳县| 镇远县|