iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C#中的委托和事件详解
  • 467
分享到

C#中的委托和事件详解

2024-04-02 19:04:59 467人浏览 安东尼
摘要

从大学就开始做C#这块,也做C#几年了,最近又从iOS转回.net,继续做C#,之前也没有写博客的习惯,写博客也是从我做ios的时候开始的,现在既然又做回了.net,那就写点关于.N

从大学就开始做C#这块,也做C#几年了,最近又从iOS转回.net,继续做C#,之前也没有写博客的习惯,写博客也是从我做ios的时候开始的,现在既然又做回了.net,那就写点关于.Net的博客,可能在大牛眼里这些都是简单基础的,不过回过头看我当时初学的时候觉得委托事件是不容易理解的,我这里也是想着联系着OC,两者有比较的学习下。毕竟都是面向对象语言,思想是相通的。

委托在OC中类似block,都是指向一个函数,其实他没和c++的函数指针类似。但委托还是和函数指针不太一样,委托是完全面向对象的,是类型安全可靠的。C++的指针仅仅指向成员函数,而委托同时封装了一个对象实例和方法。

委托声明用于定义一个从System.Delegate类派生的类。

格式:属性集 修饰符 delegate 返回值类型(A) 标识符(C)(形参列表(B));

一、委托是什么?

看上面的红字我们可以明白其实委托是一个类。其实类是什么?类也是一种数据类型,它了String类一样,也是一个数据类型,所以呢委托其实也是一个数据类型,只是这个数据类型和其他的有点不同,它这个数据类型指向的是一个函数。一个返回值为A,形参列表为B的名为标识符C的函数。其实这和OC中的block类似,block中也是用来定义函数。我们用typedef void(^myblock1)(int a,int b);来定义一个block,其实就是定义一个数据类型。上面的委托声明也是定义了一个引用类型的数据类型。

二、委托怎么用?

上面也说了,声明一个委托其实就是声明了一个数据类型,和Person、String一样都是一个数据类型。我们在使用委托和使用Person、String类型的数据一样。也是先声明:public 类型(Person、String) 变量(或属性)名。所以我们在使用委托时也是这样。只是这个变量或属性对应的是一个函数。

三、例子

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

namespace Delegate
{
    //定义了一个从System.Delegate类派生的类
    //也可以理解为一种数据类型 这种数据类型指向返回值为void 参数为Person对象的函数
    //我们也可以把Person类理解为一种数据类型 只是它包含的是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;
        }

        //既然委托是一数据类型和String一样,所以可以像声明String对象一样声明代理变量
        public EatFood eatFood;

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

    }
}

上面定义了一个Person类,也定义了一个定义了一个从System.Delegate类派生的类EatFood,同时在Person类中声明了EatFood类类型的一个变量,在eating()函数中使用了这个变量。ps:请留意上面代码中的注释。下面的代码中我们定义了两个Person对象,一个chinesePerson一个englishPerson,而分别为两个类的eatFood变量指定不同的函数。

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);
            //通过构造函数实例化对象
            chinesePerson.eatFood = new EatFood(chineseEat);
            chinesePerson.eating();

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

            Person englishPerson = new Person("Ivan",25);
            //通过直接复制来实例化对象
            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);
        }
    }
}

可以看到针对不同的对象指定不同的eatFood变量则执行的结果也不一样。

四、委托和其他数据类型的区别

上面也说了可以把委托当做是一个数据类型,但它和普通的数据类型还是有区别的。这可能就是现在的个性吧,委托也有委托的个性。

委托实例化用于创建委托实例,和类实例创建语法相同。但委托可以封装多个方法,这些方法的集合合称为调用列表。委托使用+、+=、-、-=运算符向调用列表中增加或删除方法。

我们对上面的代码稍作改动,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);
            //通过构造函数实例化对象
            chinesePerson.eatFood = new EatFood(chineseEat);
            chinesePerson.eatFood += englishEat;
            chinesePerson.eating();

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

            Person englishPerson = new Person("Ivan",25);
            //通过直接复制来实例化对象
            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);
        }
    }
}

为了促进中西交流,好多人去留学也有好多来到中国的,所以在吃的方面彼此都会吃对方的。所以要增加方法来表示吃不同的食物。有了委托可以通过+=、-=来实现增加、删除调用列表,这样就方面很多。从下面的输出结果能看到,每个Person对象都调用了chineseEat、englishEat函数。

五、好处

上面的demo也展示了委托的使用方法,通过上面的使用我们可以思考下使用它的好处。我们如果不使用委托来实现这个功能的话,我们可能会在Person类中做一个判断,判断下是Chinses还是English,可是这样的话,如果哪天有了日本、法国等,那又要多好多个判断。可扩展性不好。可能有的会说可以在Person里面定义一个虚方法,分别声明Chinese、English类继承Person类重写虚方法,这确实是一个方法,如果有新的要扩展的话可以直接创建一个新的类重写虚方法就搞定了,不过这样的话如果只是这个方法不同,就要写一个类,这样未免杀鸡用牛刀了。所以说委托还是一个不错的选择。如果不仅要增加语言还要增加方法那这就更麻烦了。有了委托这些全解决。

六、事件

对象之间的交互是通过消息传递来实现的,而事件就是对象发送的消息,通过发信号的形式通知操作的发生。引发事件的对象为事件发送方,捕获事件并对其做出响应的对象为事件接收方。在事件通信中,事件发送方不知哪个对象或方法将接收它引发的事件,所需要的是在发送方和接收方之间用一个纽带来联系,在C#中使用委托为这个纽带。

事件声明的格式:属性集 修饰符 event 委托类型 事件名。

其实说白了就是事件是对委托变量的封装。请注意上面写的,我一直写的是委托类型的变量,面向对象的三大特征之一就是封装,例如变量和属性。在上面直接使用委托来指定函数,其实这和直接使用变量一样,但是在面向对象中一般不会直接访问变量,而是对变量进行封装,例如属性{get;set;}方法。事件是对委托的封装。我们来看一下事件的使用,和上面使用委托一样,我们在Person类中声明一个事件。

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

namespace Delegate
{
    //定义了一个从System.Delegate类派生的类
    //也可以理解为一种数据类型 这种数据类型指向返回值为void 参数为Person对象的函数
    //我们也可以把Person类理解为一种数据类型 只是它包含的是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;
        }

        //既然委托是一数据类型和String一样,所以可以像声明String对象一样声明代理变量
        //public EatFood eatFood;
        //之前是直接声明委托,现在是声明一个事件
        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);
            //通过构造函数实例化对象
            chinesePerson.EatFoodEventHandler += new EatFoodDelegate(chineseEat);
            chinesePerson.EatFoodEventHandler += englishEat;
            chinesePerson.eating();

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

            Person englishPerson = new Person("Ivan", 25);
            //在委托中 可以直接使用=来给委托对象复制 而在事件中就不能直接使用= 要使用+=
            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);
        }
    }
}

上面可以看到,使用事件来实现了同样的功能。

七、委托和代理设计模式的区别

不管是使用委托或者事件其实它们都是在A对象(本例中的Person对象)中调用B对象中的方法,这与设计模式中有相似之处。具体代理设计模式这里就省略了,委托和代理都是在A对象使用B对象中的方法。不过它们还是有区别的,委托中在A中直接使用的是B中的方法,是类与方法之间的,代理设计模式中是将A类中设置一个B类变量,然后通过B来使用B中的方法,是类与类之间的。这也是我的个人理解,不知道对不对,错了的话也希望大牛指正,以免耽误了其他的社会主义接班人。

到此这篇关于C#委托和事件的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: C#中的委托和事件详解

本文链接: https://www.lsjlt.com/news/153741.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C#中的委托和事件详解
    从大学就开始做C#这块,也做C#几年了,最近又从ios转回.Net,继续做C#,之前也没有写博客的习惯,写博客也是从我做ios的时候开始的,现在既然又做回了.net,那就写点关于.N...
    99+
    2024-04-02
  • c#委托与事件(详解)
    目录前言一、声明方法二、声明委托三、实例化委托四、使用委托总结前言 .NET中的委托是一个类,它定义了方法的类型,是一个方法容器。委托把方法当作参数,可以避免在程序中大量使用条件判...
    99+
    2024-04-02
  • C#中的委托和事件
    目录一、委托1、什么是委托1.1 定义委托1.2 声明并实例化委托1.3 委托实例的调用2、委托类型和委托实例2、多种途径实例化委托3、链式委托总结二、事件1、什么是事件2、如何声明...
    99+
    2024-04-02
  • js事件委托详解
    1、每个函数都是对象,占用内存。内存中的对象越多,性能越差。解决事件处理过多问题的办法是事件委托。 2、事件委托冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。 实例 ...
    99+
    2024-04-02
  • C#委托和事件怎么理解
    这篇文章主要介绍“C#委托和事件怎么理解”,在日常操作中,相信很多人在C#委托和事件怎么理解问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C#委托和事件怎么理解”的疑惑有所帮助!接下来,请跟着小编一起来学习吧...
    99+
    2023-06-17
  • C#中的委托详解
    如果要给方法传递一个方法参数时,就可以使用委托。要传递方法,就必须把方法的细节封装在一钟新类型的对象中,即委托。委托是一种特殊类型的对象,其特殊之处在于,我们以前定义的所有对象都包含...
    99+
    2024-04-02
  • JavaScript中事件委托的示例详解
    目录事件流事件委托结尾大家好,我是前端西瓜哥。今天我们来认识一下事件委托。 所谓事件委托,就是将原本应该在当前元素绑定的事件,放到它的祖先元素上,让祖先元素来委托处理。 事件流 事件...
    99+
    2024-04-02
  • C#中怎么使用委托和事件
    在 C# 中,委托和事件是一种常用的机制,用于实现事件驱动的编程模型。委托是一种类型,用于存储对方法的引用,而事件是委托的一种特殊用...
    99+
    2024-03-06
    C#
  • C#中的委托和事件实例分析
    本文小编为大家详细介绍“C#中的委托和事件实例分析”,内容详细,步骤清晰,细节处理妥当,希望这篇“C#中的委托和事件实例分析”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。一、定义委托delegate v...
    99+
    2023-06-30
  • javascript事件冒泡,事件捕获和事件委托详解
    1、事件冒泡:在javascript事件传播过程中,当事件在一个元素上出发之后,事件会逐级传播给先辈元素,直到document为止,有的浏览器可能到window为止。并不是所有的事件...
    99+
    2024-04-02
  • 基于事件冒泡、事件捕获和事件委托详解
    事件冒泡、事件捕获和事件委托 在javascript里,事件委托是很重要的一个东西,事件委托依靠的就是事件冒泡和捕获的机制,我先来解释一下事件冒泡和事件捕获: 事件冒泡会从当前触发...
    99+
    2024-04-02
  • C#中事件和委托的区别是什么
    事件是一种特殊的委托,委托是一种类型安全的函数指针,而事件是委托的一种封装,它只能在其所在的类中被触发和订阅。 委托可以被任何类访问...
    99+
    2024-04-03
    C#
  • C#中的多播委托和泛型委托
    多播委托 简介 每一个委托都是继承自MulticastDelegate,也就是每个都是多播委托。带返回值的多播委托只返回最后一个方法的值多播委托可以用加减号来操作方法的增加或者减少。...
    99+
    2024-04-02
  • C#中如何实现事件和委托的编译
    这篇文章给大家分享的是有关C#中如何实现事件和委托的编译的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。C#事件和委托的编译需求操作C#事件时,有时会得到编译错误:事件“Delegate.GreetingManag...
    99+
    2023-06-18
  • C#中委托、事件和回调的使用及说明
    目录委托的使用案例事件的使用案例带参数的事件案例回调函数的使用案例委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以...
    99+
    2024-04-02
  • C#委托用法详解
    目录1、什么是委托2、委托的定义3、委托的实例化3.1 使用new关键字3.2 使用匿名方法3.3 使用Lambda表达式4、泛型委托5、C#内置泛型委托6、多播委托1、什么是委托 ...
    99+
    2024-04-02
  • js事件流、事件委托与事件阶段实例详解
    目录前言1、事件流2、事件处理程序3、事件对象4、跨浏览器事件处理5、事件委托总结前言 JavaScript 与 HTML 的交互是通过事件实现的,事件代表文档或浏览器窗口中某个有意...
    99+
    2024-04-02
  • C#中如何使用委托和事件处理程序
    C#中如何使用委托和事件处理程序,需要具体代码示例在C#中,委托和事件处理程序是两个非常重要的概念,它们可以用于实现事件驱动的编程模型。委托提供了一种将方法作为参数传递的机制,而事件处理程序则用于处理特定事件的方法。本文将详细介绍C#中如何...
    99+
    2023-10-22
    委托 (Delegate) 事件处理程序 (Event Handler) C# 中的事件 (Events in C#)
  • Javascript 中怎么实现事件流和事件委托
    今天就跟大家聊聊有关Javascript 中怎么实现事件流和事件委托,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。javascript 事件流和事件...
    99+
    2024-04-02
  • 如何理解javascript事件委托
    这篇文章主要介绍“如何理解javascript事件委托”,在日常操作中,相信很多人在如何理解javascript事件委托问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”如何理解...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作