C_+中的委托和事件

合集下载

C#委托、事件、线程

C#委托、事件、线程

C#委托、事件、线程这是⼏个简单的例⼦,但是实际的开发中委托还还只在反射时⽤到过,事件的话只⾃⼰做了⼀次,并且还是特意去⽤的,实际上可以不⽤。

线程的话,因为需要,所以⽤的会多点,这⾥主要是WS上的线程。

委托在前⾯的反射实例中,也有⽤到委托执⾏⽅法。

这个例⼦是将⼀个⽅法或者委托实例作为另外⼀个函数的⼊参传递。

⾄于有什么⽤,我现在还没⽤上。

private delegate void Dosth(string s);//定义委托⽆返回值⼀个string参数private void button2_Click_1(object sender, EventArgs e){Dosth dosth = new Dosth(Func);//实例化委托,DoMain(dosth);//DoMain(Func) 调⽤函数⽅法DoMain,⼊参可以是对应的⽅法Func也可以是委托实例化的后的dosth}private void Func(string s){MessageBox.Show(s);}private void DoMain(Dosth fun) //⽅法DoMain ⼊参接收⼀个委托实例或者函数:返回值是空,⼊参是⼀个string{fun("hello world!");}事件事件使⽤发布-订阅模型,事件在类中申明且⽣成,通过使⽤同⼀个类或者其他类中的委托与事件处理程序关联。

包含事件的类⽤于发布事件,被称为发布器,其他接收该事件的类称为订阅器。

发布器中描述的是怎么调⽤事件,也就是触发事件,订阅器中实际是事件具体的执⾏,最终要做什么在订阅器中完成。

这是⼀个实例。

发布器类发布事件,定义触发事件执⾏的逻辑的设定。

public class Publish {private int value;public delegate void MyDelegate(string s);//申明委托public event MyDelegate MyEvent;//基于申明的委托定义事件public Publish(){value = 3;}public void CompairValue(int n){if (n == value)//满⾜条件{OnValueChanged();}}protected void OnValueChanged(){if (MyEvent != null){MyEvent("hello world!");//触发订阅器中的⽅法执⾏}}}订阅器类被触发时,做该做的事。

c#中委托,事件和BeginInvoke在进程间传递消息的作用

c#中委托,事件和BeginInvoke在进程间传递消息的作用
sp.ReadBufferSize = 256; try {
sp.Open(); } catch (Exception) {
} } public void spReceive_DataReceived(object sender, SerialDataReceivedEventArgs e) {
byte[] readBuffer = new byte[sp.ReadBufferSize]; sp.Read(readBuffer, 0, readBuffer.Length);
○4 if (spDataReceived != null)//这句话是检测事件列表是否有添加函数
spDataReceived(this,readBuffer,sp.ReadBufferSize);//这句话就是事件调用,注意其中的参数列表, 和定义的委托是相对应的。当串口有数据接收的时候,spReceive_DataReceived会被自动执行,在执行这个函数的时 候,spDataReceived事件也会被触发。
namespace Fibe_Monitor {
public partial class Form1 : Form {
Serial_Control sc = new Serial_Control();//这句话是对上面那个cs文件里面的Serial_Control类进行实例化。
○7 public delegate void dataReceiveInvoke(string str1);//要使用BeginInvoke也得定义一个委托,同样注意委托
首先,我来给大家理理委托、事件和往事件里添加的函数之间的关系吧,他们具体的原理我就不赘述了。首先, 事件是基于委托的,我们要先定义一个委托(delegate),然后用委托去声明一个事件(event),然后再利用事件和委 托往事件里添加函数,也就是所谓的事件列表,当这个事件被触发(相当于就是一个函数调用)时,添加到事件列 表里的函数就会依次执行。有一点需要注意,声明的委托的参数列表和往事件里添加的函数的参数列表必须一样, 在调用事件的时候,事件传递的参数列表也得和委托一致,这样事件一旦触发,事件列表里面的函数就会获取到事 件触发时传递过来的参数。 下面贴出我写的串口通讯程序,注重看黄色部分和后面的注释,按照我写的顺序看,至于其他没标注的,如果你对 串口通讯不感兴趣,就没必要看了: using System; using System.Collections.Generic; using System.Text; using System.IO.Ports; using System.Threading; namespace Fibe_Monitor {

委托及事件响应button_click

委托及事件响应button_click

C#事件及响应方法——让你明白private void button1_Click(object se nder, System.EventArgs e)C#语言自C/C++演变而来。

它是现代、简单、完全面向对象和类型安全的。

C#语言是微软公司针对.Net平台才推出来的一门新语言,作为.Net平台的第一语言,它几乎集中了所有关于软件开发和软件工程研究的最新成果。

面向对象、类型安全、组件技术、自动内存管理、跨平台异常处理、版本控制、代码安全管理……在.NET应用程序开发中,不管是WEB Forms()还是Windows Forms,都涉及到大量对象的事件响应及处理,比如客户在线提交一份订单、或是在Windows窗口上移动鼠标等都将有事件发生。

那么在C#中,是怎样声明事件并为事件添加响应方法的呢?下面的文章对此为大家作了详细的讲述。

原理简介在C#中,一个类可以有域(Fields)、属性(Properties)、方法(Methods)、索引(Ind exs)、事件(Events)等成员,其中事件(Events)成员就是用来声明一个类事件的。

在类中声明一个事件成员一般采用如下的语法形式:public event 代表名事件名。

如在Control类中声明了一个Click事件成员,其语法如下:public event EventHandler Click;在C#中,增加了一个新的数据类型delegate(代表)来解决事件处理问题。

代表数据类型非常类似于C语言中的指针,其与指针不同的是,其是代码是安全的,可管理的。

由于C#本身的简易性,对于没有使用过C及指针的程序来说,理解delegate也是非常容易的。

在C#中,通过使用delegate,你可以通过“+=”(加等于)操作符非常容易地为.Ne t对象中的一个事件添加一个甚至多个响应方法;还可以通过非常简单的“-=”(减等于)操作符取消这些响应方法。

如下面为temp按钮添加Click事件的语句:temp.Click+=new System.EventHandler(this.Test);//为test添加事件处理方法在上面声明事件的语句中,Eventhandler是一个delegate(代表)类型,其在.Net类库中如下声明的:public delegate void EventHandler(object sender,EventArgs e);这样,所有形如:void 函娄名(object 参数名,EventArgs参数名);的函数都可以作为Co ntrol类的Click事件响应方法了。

C#基础知识学习之?委托(delegate)与事件(event)之间的介绍

C#基础知识学习之?委托(delegate)与事件(event)之间的介绍

C#基础知识学习之✨委托(delegate)与事件(event)之间的介绍委托(delegate) 与事件(event)前言在之前的文章里介绍了C#中的委托(delegate)(Action、Func、Predicate)的基本含义及用法那本篇文章在这里还要介绍一个跟委托有很大关系的小伙伴——C#中的事件(event)事件跟委托是有很大联系的,所以也就导致很容易分不清他们两个,以及什么时候用这两个上面有博客提到委托,想单独了解委托的可以去看一下,本篇文章主要说一下什么是事件以及事件与委托的区别委托和事件的定义委托在这里再说一遍委托跟事件的简单定义(没有搜到特别准确的,都是大概定义,理解万岁)委托:delegate 是一种可用于封装命名或匿名方法的引用类型。

委托类似于 C++ 中的函数指针;但是,委托是类型安全和可靠的。

委托是一种动态调用方法的类型,属于引用型。

委托是对方法的抽象和封装。

委托对象实质上代表了方法的引用(即内存地址)委托允许将方法作为参数进行传递。

委托可用于定义回调方法。

委托可以把多个方法链接在一起。

这样,在事件触发时可同时启动多个事件处理程序。

委托签名不需要与方法精确匹配。

事件事件:事件是特殊类型的多路广播委托,仅可从声明它们的类或结构(发行者类)中调用。

如果其他类或结构订阅了该事件,则当发行者类引发该事件时,会调用其事件处理程序方法。

事件表示C#中已定义的一个对象,即处理通知过程的对象通常,每个事件的发生都会产生发送方和接收方。

在.net框架中,事件是将事件发送者(触发事件的对象)与事件接受者(处理事件的方法)相关联的一种代理类,即事件机制是通过代理类来实现的。

当一个事件被触发时,由该事件的代理来通知(调用)处理该事件的相应方法委托和事件的区别简单说了一下两者的定义,眼神好的小伙伴这时候就会发现,事件的说明里有提到一句话:“事件也可以算一种特殊的委托”,这句话不是特别准确,但是也不妨可以这样理解。

C#程序设计语言中的委托和事件

C#程序设计语言中的委托和事件


委 托 的定 义 格 式 如 下 :
【t b t 】 【 o i r e gt r u —y e i n f r a r u s m df s l a e l t d ti ti e i 】d e e s t p e ie e (o a p rm t ] [ r l aa e r ) fm - e ; s
对一个 方法 的 引用 . 个方 法可 以是 静态 方法 . 这 也可 以是实例 的方法 , 只要 这些方 法具有 相 同的签名 ( i Sg .
实 际 上 .#编译 器将 为 每一 个委 托 类 型 自动生 C 成 一个新类 的定义 . 类派 生 自.E rme ok中的 新 N TFa w r
M A NlFE 5t
幽∞ I _ . e v te x
传 递参 数 。 要 引 用 这 两个 方 法 .声 明代 理类 型 go Lf odi e如
下:
P bi d l a o o d i O / a es n t e u l e gt vi g o Lf ;/ m g a r c e e d e s i u
维普资讯
\、
竺竺竺
C #程序 设计语 言 中的委托和事件
曹 文
( 南 信 息 职 业 技 术 学 院 , 沙 4 0 01 湖 长 10 )

要 :委托 和 事件 是 c≠ 中的两个重要 概念 , j } 也是 初 学者 的难点 。 大多数教 科 书 中对这 两 但
相 关 方 法
1 实例化委托 对 象 . 2
与所有 的对象一 样 . 新的委 托对象 也是用 nw操 e
作 符创 建 , 但传 递 给 n w表 达式 的参 数 特殊 。 的写一 e 它

Unity+C#游戏开发接口,委托与事件

Unity+C#游戏开发接口,委托与事件

游戏开发第五章接口,委托与目录 CONTENTS五.一接口零一五.二委托零二五.三零三内容简述"接口"理解为就是定义一套标准,然后由实现类来具体实现其地方法,接口就是一组类地抽象。

"委托"理解为"方法地抽象",也就是说定义一个方法地模板,至于这个方法具体是怎么样地,就由方法自己去实现。

是用户操作,例如:按键,点击,鼠标移动等。

或者某些,例如:系统生成地通知。

应用程序需求响应发生时。

五.一接口接口(interface)是C#地一种数据类型,属于引用类型。

一个接口定义一个协定。

接口可以包含方法,属,与索引器,接口本身不提供它所定义地成员地实现,接口只指定实现该接口地类或结构需要提供地成员。

实现某接口地类需要遵守该接口定义地协定,即需要提供接口成员地实现。

五.一.一 . 接口地定义一.定义接口是指定一组函数成员而不实现成员地引用类型,其它类型与接口可以继承接口。

二.特点通过接口可以实现多重继承,接口里面地方法都需求由外面接口实现去实现方法体,那么其修饰符必然是public。

接口成员不能有new,static,abstract,override,virtual修饰符。

接口只包含成员地签名,接口没有构造函数,所有不能直接使用new对接口行实例化。

C#是单继承,接口是解决C#里面类可以同时继承多个基类地问题。

五.一.二接口地使用接口地声明在C#,声明接口使用interface关键字,一般形式如下:[访问修饰符] interface 接口名[ : 基接口列表]{//接口成员}说明:接口成员可以是属,方法,索引器与,不能包含字段,构造函数等。

所有接口成员隐式地具有了public访问修饰符,因此,接口成员不能添加任何访问修饰符。

接口主要用来定义一个规则,让企业内部或行业内部地软件开发员按标准去实现应用程序地功能。

因此,继承接口地类或结构需要实现接口地所有属,方法,索引器与,继承接口地方法与继承类相似 接口地继承接口也可以继承其它接口,而接口可以多继承,即接口可以从多个接口继承,基接口名之间用逗号分隔。

委托和事件的区别

委托和事件的区别

委托和事件的区别(讲的很详细)--转委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。

它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在。

本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.Net Framework中的委托和事件、委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论。

将方法作为方法的参数我们先不管这个标题如何的绕口,也不管委托究竟是个什么东西,来看下面这两个最简单的方法,它们不过是在屏幕上输出一句问候的话语:public void GreetPeople(string name) {// 做某些额外的事情,比如初始化之类,此处略EnglishGreeting(name);}public void EnglishGreeting(string name) {Console.WriteLine("Morning, " + name);}暂且不管这两个方法有没有什么实际意义。

GreetPeople用于向某人问好,当我们传递代表某人姓名的name参数,比如说“Jimmy”,进去的时候,在这个方法中,将调用EnglishGreeting方法,再次传递name参数,EnglishGreeting则用于向屏幕输出“Morning, Jimmy”。

现在假设这个程序需要进行全球化,哎呀,不好了,我是中国人,我不明白“Morning”是什么意思,怎么办呢?好吧,我们再加个中文版的问候方法:public void ChineseGreeting(string name){Console.WriteLine("早上好, " + name);}这时候,GreetPeople也需要改一改了,不然如何判断到底用哪个版本的Greeting问候方法合适呢?在进行这个之前,我们最好再定义一个枚举作为判断的依据:public enum Language{English, Chinese}public void GreetPeople(string name, Language lang){//做某些额外的事情,比如初始化之类,此处略swith(lang){case Language.English:EnglishGreeting(name);break;case Language.Chinese:ChineseGreeting(name);break;}}OK,尽管这样解决了问题,但我不说大家也很容易想到,这个解决方案的可扩展性很差,如果日后我们需要再添加韩文版、日文版,就不得不反复修改枚举和GreetPeople()方法,以适应新的需求。

c事件和委托的区别

c事件和委托的区别

c事件和委托的区别
委托和事件在Net Framework中的应用非常厂泛,然而,较好地理解委托和事件。

对很多接触C#时间不长的人来说并不容易。

它们就像是一道槛儿, 过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别得慌,混身不自在。

1.委托的作用:
在不知道要执行的方法的具体代码时,可以先用一个委托变量来代替方法调用,注意委托的返回值,参数列表要确定,在实际调用之前,需要为委托赋值,否则为null。

2.事件的作用:
事件的作用和委托变量一样,只是功能上比委托变量有更多的限制,第一好比如只能通过+=或者=来绑定事件处理程序(方法),第二只能在类内部去触发事件,感觉事件这个东西在winform程序里面用的比较多,平时封装的代码应该比较少用到这个。

3.委托和事件的关系:
从反编译Q的角度看IL代码的时候,事件的本质其实是由一个私有的委托变量和add_和remove_ 方法组成。

事件、索引、属性本质都是方法,在接口里面只能定义方法,所以事件、索引、属性他们可以被定义在接口里面。

C中的委托的使用和讲解

C中的委托的使用和讲解

C#中的委托引言委托和事件在.NetFramework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。

它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在。

本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.NetFramework中的委托和事件、委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论。

将方法作为方法的参数我们先不管这个标题如何的绕口,也不管委托究竟是个什么东西,来看下面这两个最简单的方法,它们不过是在屏幕上输出一句问候的话语:1publicvoid GreetPeople(string name){2//做某些额外的事情,比如初始化之类,此处略3EnglishGreeting(name);4}1publicvoid EnglishGreeting(string name){2Console.WriteLine("Morning,"+name);3}暂且不管这两个方法有没有什么实际意义。

GreetPeople用于向某人问好,当我们传递代表某人姓名的name参数,比如说“JiYF”,进去的时候,在这个方法中,将调用EnglishGreeting方法,再次传递name参数,EnglishGreeting则用于向屏幕输出“Morning,JiYF”。

现在假设这个程序需要进行全球化,哎呀,不好了,我是中国人,我不明白“Morning”是什么意思,怎么办呢?好吧,我们再加个中文版的问候方法:1publicvoid ChineseGreeting(string name){2Console.WriteLine("早上好,"+name);3}这时候,GreetPeople也需要改一改了,不然如何判断到底用哪个版本的Greeting 问候方法合适呢?在进行这个之前,我们最好再定义一个枚举作为判断的依据:1publicenum Language{2English,Chinese3}1publicvoid GreetPeople(string name,Languagelang){2//做某些额外的事情,比如初始化之类,此处略3swith(lang){4case Language.English:5EnglishGreeting(name);6break;7case Language.Chinese:8ChineseGreeting(name);9break;10}11}OK,尽管这样解决了问题,但我不说大家也很容易想到,这个解决方案的可扩展性很差,如果日后我们需要再添加韩文版、日文版,就不得不反复修改枚举和GreetPeople()方法,以适应新的需求。

委托和事件及函数指针的区别

委托和事件及函数指针的区别

委托和事件及函数指针的区别1.委托和事件的区别:⾸先最⼤的区别在于委托是⼀个类型,⽽事件最多只能算是⼀个委托类型的变量.事件作为委托类型的变量时,是私有的,但提供两个⽅法,⼀个是add⼀个remove⽤以追加和删除事件元素.在这私有访问修饰符和两个默认⽅法的基础上可以展现出事件与委托在安全层⾯上的区别,委托对象是公有的,在任何地⽅都可以被调⽤,因⽽难以避免被随意调⽤和冒名触发.且除了多播委托的追加和移除⽅法是⽤+=和-=,此外委托对象的赋值都是使⽤=号,这种赋值⽅法在追加⽅法时容易误操作⽽清空委托对象内原本的内容.⽽事件则不同,⾸先事件是在委托对象的基础上加了event关键字.加了event关键字之后,这个委托对象在编辑器⾥的图标已经从原本的蓝⾊格⼦变成了⼀道屎黄⾊的闪电,这⼀个改变是巨⼤的,就像成⼈礼⼀般.是标志着⼀个⼩对象从此长⼤成了事件.⽽改变之后的事件君已经完全与委托对象这种⼩正太不同了,再也不是任⼈调⽤,想改就改的了.因为事件君的私有特征,除了声明⾃⼰的类可以调⽤,此外任何地⽅都不能被调⽤,这就妥善的完爆了那些能调戏对象还想调戏事件君的外部类和外部⽅法.⽽事件君⼜留有⼀个形似属性中getset的与外部联系的出⼊⼝,即remove和add⽅法.⽤以移除和追加事件,但是任谁也不能像欺负委托对象那样,⽤⼀个=号就把原本的内容给替换了,因为事件君不认识啥是等号.此外事件君也不能⽤来给别的事件赋值,因为事件君说了,它只站在+=或-=的左边,⾄于右边嘛,呵呵,不如你去问问对象君?2.委托与函数指针的区别:委托具有⾯向对象的特征,⽽指针是⼀个⾯向过程的函数,指针只是表⽰⼀个地址或指向,⽽委托这个C#中的概念有着⾮常明确的层级结构.从object这个⾯向对象的根类开始往下追溯,Delegate类就是委托的超级⽗类,由于委托对象能接受多个⽅法,即多播委托的存在,因为在Delegate类下有⼀个叫做MulticastDelegate类在⽀持多播委托,这个类中,有两个字段,⼀个是_invocationCount⽤以记录个中元素的数量,⼀个是_invocationList,这个其实是object类型的数组,⽤以存储接收到的委托变量的值,且这个数组的原始⼤⼩及capacity的增长都是编译器⾃动完成.当然由于它是数组,那么想遍历个中元素也是可以的.遍历时通过⼀个强制类型转换,从object类转换成相应类型后还是可以逐个访问.⽽multicastDelegate是直接派⽣出⽤户⾃定义的委托类型的类.因⽽⽤户⾃定义的委托类型依然具备这些类成员,在⽤户⾃定义的委托类型中有个字段叫做_taget.给这个委托对象的赋值就是由这个字段接收并在上级类即MulticastDelegate类继承来的_invocationList集合中加上该值.这就是委托通过继承展现出来的层级结构,这是委托的⼀⼤特征.⽽指针君,是没有的.。

Csharp中委托,事件理解入门

Csharp中委托,事件理解入门

C sharp 中委托,事件理解入门C#中委托,事件理解入门目录, 导论 , 什么是委托 , 事件的理解 , 事件关键字 , 最后导论在学习C#中的委托和事件过程中,我读了许多文章来理解他们二者究竟是怎么一回事,以及如何使用他们,现在我将整个的理解过程陈述以下,我学到的每一方面,恐怕也是你们需要掌握的。

什么是委托,委托和事件这两个概念是完全配合的。

委托仅仅是函数指针,那就是说,它能够引用函数,通过传递地址的机制完成。

委托是一个类,当你对它实例化时,要提供一个引用函数,将其作为它构造函数的参数。

每一个委托都有自己的签名,例如:Delegate int SomeDelegate(string s, bool b);是一个委托申明,在这里,提及的签名,就是说SomeDelegate 这个委托有string 和 bool 类型的形参,返回一个int 类型。

上面提及的:当你对委托实例化时,要提供一个引用函数,将其作为它构造函数的参数。

这里要注意了:被引用的这个函数必须和委托有相同的签名。

看下面的函数:private int SomeFunction(string str, bool bln){...}你可以把这个函数传给SomeDelegate的构造函数,因为他们有相似的签名(in other words,他们都有相同的形参类型和个数,并且返回相同的数据类型)。

SomeDelegate sd = new SomeDelegate(SomeFunction);sd 引用了 SomeFunction,也就是说,SomeFunction已被sd所登记注册,如果你调用 sd,SomeFunction 这个函数也会被调用,记住:我所说 SomeFunction 的含义,后面,我们会用到它。

现在,你应该知道如何使用委托了,让我们继续理解事件之旅……事件的理解我们知道,在C#中:, 按钮(Button)就是一个类,当我们单击它时,就触发一次click事件。

C#——类的事件

C#——类的事件

C#——类的事件⼀介绍委托和事件事件是特殊化的委托,委托是事件的基础,所以在介绍事件之前先介绍⼀下委托。

委托:使⽤委托可以将⽅法应⽤(不是⽅法)封装在委托对象内,然后将委托对象传递给调⽤⽅法的代码,这样编译的时候代码就没有必要知道调⽤哪个⽅法。

通过使⽤委托程序能够在运⾏时动态的调⽤不供的⽅法。

事件:事件是对象发送的消息,发送信号通知客户发⽣了操作。

这个操作可能是由⿏标单击引起的,也可能是由某些其他的程序逻辑触发的。

事件的发送⽅不需要知道那个对象或者⽅法接收它引发的事件,发送⽅只需知道在它和接收⽅之间存在的中介(Deletgate)⼆.声明事件(定义事件)在GUI图形界⾯中的事件(单击按钮或者选择菜单等)是已经定义好的事件,所需要的就是注册事件。

我们也可以⾃⼰定义声明事件,可以将⾃⼰定义的事件应⽤到程序的任何地⽅。

事件和委托是分不开的,c# 中使⽤委托来声明事件。

如果在类⾥⾯声明事件,那么必须先声明该事件的委托类型,也可以使⽤⼀个事先已经声明好的委托类型。

下⾯是⼀个声明事件的例⼦:using system;public delegate void MenuHandler()//事先申明⼀个委托,也可以在类的内部声明委托类型public class Menuitem //声明⼀个菜单项⽬的类{public event MenuHadler MenuSelection;// 声明⼀个事件并指定它的委托类型string text ;//声明⼀个字符串public MenuItem(string text) //菜单项⽬类的构造函数{this.text=text; // 初始化text字符串}public void Fird(){MenuSelection; //定义⼀个触发事件的⽅法(后⾯将⽤到)}public string Text //定义属性{get{return text;}set{text=value;}}}程序⾸先定义个⼀个叫做MenuHandler的委托,然后定义了叫做 MenuItem 的类,MenuItem类包含了⼀个MenuSelection 事件(菜单被选择事件),事件的委托类型是MenuHandler。

详解C#委托,事件与回调函数

详解C#委托,事件与回调函数

详解C#委托,事件与回调函数.Net编程中最经常用的元素,事件必然是其中之一。

无论在还是WINFrom开发中,窗体加载(Load),绘制(Paint),初始化(Init)等等。

“protected void Page_Load(object sender, EventArgs e)”这段代码相信没有人不熟悉的。

细心一点一定会发现,非常多的事件方法都是带了“object sender, EventArgs e”这两个参数。

这是不是和委托非常相似呢?一、委托(有些书中也称为委派)委托是什么呢?这个名字的意思已经赋予了我们想象的空间,你是编程的,你现在正在写一个网页,而JS是你不熟悉的,于是你委托你的一位同事来帮助你完成JS部分。

这就是委托,把你所不能做的事情交给其他人去做。

而怎么知道是哪个人去做呢?当然是要知道名字!而为了区别名字一样的不同人,因此,需要描述一个特征。

在C#中,委托的作用是这样描述的:委托就像一个函数的指针,在程序运行时可以使用它们来调用不同的函数。

这个其实和你委托同事完成 JS代码一样。

如果有两位同事可以做这件事情,他们只要做的结果能够满足你的需求(就像一个接口),尽管他们做的过程不一样,并且作出的效果也不一样,但是,能够达到你的要求就可以了。

1.简单的委托那委托需要承载哪些信息呢?首先,它存储了方法名,还有参数列表(方法签名),以及返回的类型。

比如:delegate string/*返回类型*/ ProcessDelegate(int i);这就是一个委托的定义。

蓝色部分是声明委托的关键字,红色部分是返回的类型,而黑色部分是委托的类型名,和一个类名差不多,而()里的就是参数部分。

它的意思是,你要使用这个委托来做事情的话,那么,做事情的方法必须满足以下条件:1、返回类型和委托的返回类型一致,这里是string类型;2、能且只能有一个参数,并且是int类型。

OK,满足以上两个条件,一切就可以工作了:)例如:1 using System;2 using System.Collections.Generic;3 using System.Text;45 namespace TestApp6 {7 /// <summary>8 /// 委托9 /// </summary>10 /// <param name="s1"></param>11 /// <param name="s2"></param>12 /// <returns></returns>13 public delegate string ProcessDelegate(string s1, string s2);1415 class Program16 {17 static void Main(string[] args)19 /* 调用方法 */20 ProcessDelegate pd = new ProcessDelegate(new Test().Process);21 Console.WriteLine(pd("Text1", "Text2"));22 }23 }2425 public class Test26 {27 /// <summary>28 /// 方法29 /// </summary>30 /// <param name="s1"></param>31 /// <param name="s2"></param>32 /// <returns></returns>33 public string Process(string s1,string s2)34 {35 return s1 + s2;36 }37 }38 }输出的结果是:Text1Tex22、泛型委托泛型的委托,就是然参数的类型不确定,例如代码改写为:using System;using System.Collections.Generic;using System.Text;namespace TestApp{/// <summary>/// 委托/// </summary>/// <param name="s1"></param>/// <param name="s2"></param>/// <returns></returns>public delegate string ProcessDelegate<T,S>(T s1, S s2);class Program{static void Main(string[] args){/* 调用方法 */ProcessDelegate<string,int> pd = new ProcessDelegate<string,int>(new Test().Process); Console.WriteLine(pd("Text1", 100));}public class Test{/// <summary>/// 方法/// </summary>/// <param name="s1"></param>/// <param name="s2"></param>/// <returns></returns>public string Process(string s1,int s2){return s1 + s2;}}}输出的结果就是:Text1100泛型的详细内容不属于本文的介绍范围,这里不加多说了。

c委托与事件简单实例

c委托与事件简单实例

c委托与事件简单实例委托与事件是C#中常用的一种编程模式,它们可以让程序员更加灵活地控制程序的流程流转,使得程序的代码结构更加清晰,可读性更高。

在本文中,我们将以一个简单的例子来介绍委托与事件的使用方法,并探讨它们的一些重要特性。

假设我们正在开发一个游戏,这个游戏中有一个角色需要在不同场景下播放不同的动画。

我们可以使用一个委托来实现这个功能。

首先,我们需要声明一个委托类型,用来描述我们需要播放的动画:``` csharpdelegate void PlayAnimation(string animation);```这个委托类型表示一个接受一个字符串参数的方法,这个方法的返回值为 void,也就是没有返回值。

接着,我们可以定义一个包含这个委托类型为参数的方法:``` csharpvoid ChangeScene(PlayAnimation playAnimation){// 模拟切换场景的过程Console.WriteLine("正在切换场景……");// 播放动画playAnimation("idle");// 模拟切换场景完成的过程Console.WriteLine("场景切换完成!");}```这个方法接受一个 PlayAnimation 类型的参数 playAnimation,它的作用是在切换场景的过程中,播放一个名为 "idle" 的动画。

接下来,我们可以编写另外两个方法来实现这个委托:``` csharpvoid PlayIdle(string animation){Console.WriteLine("播放 " + animation + " 动画!");}void PlayWalk(string animation){Console.WriteLine("播放 " + animation + " 动画!");}```这两个方法是 PlayAnimation 类型的委托所需要的方法,它们接受一个字符串参数,用于指定播放的动画名称。

C#面向对象编程-委托和事件习题

C#面向对象编程-委托和事件习题
Console.write(i.ToString());
}
}
a)代码中存在错误,delegate void D(int i);不能定义在命名空间或者类之外
b)代码中存在错误,代码行V(new D(R));使用委托错误
c)程序正常运行,输出为0
d)程序正常运行,输出为210
C#面向对象编程-委托和事件
1.一个委托在某一时刻()指向多个方法。
a)可以
b)不可以
2.将事件通知其他对象的对象称为()
a)发布方
b)订户
c)通知方
3.以下的C#代码:
using System;
using System.Theading;
class App{
Public static voidMain()
b)代码正确编译和运行,并输出两次“将信寄往北大青鸟阿博泰克”;
c)代码将出现编译错误,
d)代码将编译正确,但运行时出现异常。
9>在C#中,假如有一个名为”MessageDelegate”的委托,下列能够正确定义
一个事件的是()
a)public delegate MessageDelegate messageEvent
Public class Carrier{
Public event SendMailDelegate sendEvent;
Static voidMain(){
Carrier t = new Carrier(); //1
t.sendEvent+= new SendMailDelegate(t_sendEvent);//2
b)public MessageDelegate messageEvent
c)private event MessageDelegate(messageEvent)

C#中委托和事件的区别

C#中委托和事件的区别

C#中委托和事件的区别⼤致来说,委托是⼀个类,该类内部维护着⼀个字段,指向⼀个⽅法。

事件可以被看作⼀个委托类型的变量,通过事件注册、取消多个委托或⽅法。

本篇分别通过委托和事件执⾏多个⽅法,从中体会两者的区别。

□通过委托执⾏⽅法class Program{static void Main(string[] args){Example example = new Example();example.Go();Console.ReadKey();}}public class Example{public delegate void DoSth(string str);internal void Go(){//声明⼀个委托变量,并把已知⽅法作为其构造函数的参数DoSth d = new DoSth(Print);string str = "Hello,World";//通过委托的静态⽅法Invoke触发委托d.Invoke(str);}void Print(string str){Console.WriteLine(str);}}以上,○在CLR运⾏时,委托DoSth实际上就⼀个类,该类有⼀个参数类型为⽅法的构造函数,并且提供了⼀个Invoke实例⽅法,⽤来触发委托的执⾏。

○委托DoSth定义了⽅法的参数和返回类型○通过委托DoSth的构造函数,可以把符合定义的⽅法赋值给委托○调⽤委托的实例⽅法Invoke执⾏了⽅法但,实际上让委托执⾏⽅法还有另外⼀种⽅式,那就是:委托变量(参数列表)public class Example{public delegate void DoSth(object sender, EventArgs e);internal void Go(){//声明⼀个委托变量,并把已知⽅法作为其构造函数的参数DoSth d = new DoSth(Print);object sender = 10;EventArgs e = new EventArgs();d(sender, e);}void Print(object sender, EventArgs e){Console.WriteLine(sender);}}以上,○委托DoSth的参数列表和⽅法Print的参数列表还是保持⼀致○委托DoSth中的参数object sender通常⽤来表⽰动作的发起者,EventArgs e⽤来表⽰动作所带的参数。

C#委托及事件

C#委托及事件

C#委托及事件在C#中,委托(delegate)是一种引用类型,在其他语言中,与委托最接近的是函数指针,但委托不仅存储对方法入口点的引用,还存储对用于调用方法的对象实例的引用。

简单的讲委托(delegate)是一种类型安全的函数指针,首先,看下面的示例程序,在C++中使用函数指针。

首先,存在两个方法:分别用于求两个数的最大值和最小值。

int Max(int x,int y){return x>y?x:y;}int Min(int x,int y){return x<Y?X:Y;< font>}上面两个函数的特点是:函数的返回值类型及参数列表都一样。

那么,我们可以使用函数指针来指代这两个函数,并且可以将具体的指代过程交给用户,这样,可以减少用户判断的次数。

下面我们可以建立一个函数指针,将指向任意一个方法,代码如下所示://定义一个函数指针,并声明该指针可以指向的函数的返回值为int类型,参数列表中包//括两个int类型的参数int (*p)(int,int);//让指针p指向Max函数p=max;//利用指针调用Maxc=(*p)(5,6);我们的问题在于,上面的代码中,为什么不直接使用Max函数,而是利用一个指针指向Max之后,再利用指针调用Max函数呢?实际上,使用指针的方便之处就在于,当前时刻可以让指针p指向Max,在后面的代码中,我们还可以利用指针p再指向Min函数,但是不论p指向的是谁,调用p时的形式都一样,这样可以很大程度上减少判断语句的使用,使代码的可读性增强!在C#中,我们可以使用委托(delegate)来实现函数指针的功能,也就是说,我们可以像使用函数指针一样,在运行时利用delegate动态指向具备相同签名的方法(所谓的方法签名,是指一个方法的返回值类型及其参数列表的类型)。

6.1 使用委托(delegate)6.1.1委托的建立建立委托(delegate),过程有点类似于建立一个函数指针。

相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

C# 中的委托和事件引言委托和事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易。

它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在。

本文中,我将通过两个范例由浅入深地讲述什么是委托、为什么要使用委托、事件的由来、.Net Framework中的委托和事件、委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论。

将方法作为方法的参数我们先不管这个标题如何的绕口,也不管委托究竟是个什么东西,来看下面这两个最简单的方法,它们不过是在屏幕上输出一句问候的话语:public void GreetPeople(string name) {// 做某些额外的事情,比如初始化之类,此处略EnglishGreeting(name);}public void EnglishGreeting(string name) {Console.WriteLine("Morning, " + name);}暂且不管这两个方法有没有什么实际意义。

GreetPeople用于向某人问好,当我们传递代表某人姓名的name参数,比如说“Jimmy”,进去的时候,在这个方法中,将调用EnglishGreeting方法,再次传递name参数,EnglishGreeting 则用于向屏幕输出“Morning, Jimmy”。

现在假设这个程序需要进行全球化,哎呀,不好了,我是中国人,我不明白“Morning”是什么意思,怎么办呢?好吧,我们再加个中文版的问候方法:public void ChineseGreeting(string name){Console.WriteLine("早上好, " + name);}这时候,GreetPeople也需要改一改了,不然如何判断到底用哪个版本的Greeting问候方法合适呢?在进行这个之前,我们最好再定义一个枚举作为判断的依据:public enum Language{English, Chinese}public void GreetPeople(string name, Language lang){//做某些额外的事情,比如初始化之类,此处略swith(lang){case Language.English:EnglishGreeting(name);break;case Language.Chinese:ChineseGreeting(name);break;}}OK,尽管这样解决了问题,但我不说大家也很容易想到,这个解决方案的可扩展性很差,如果日后我们需要再添加韩文版、日文版,就不得不反复修改枚举和GreetPeople()方法,以适应新的需求。

在考虑新的解决方案之前,我们先看看 GreetPeople的方法签名:public void GreetPeople(string name, Language lang)我们仅看 string name,在这里,string 是参数类型,name 是参数变量,当我们赋给name字符串“jimmy”时,它就代表“jimmy”这个值;当我们赋给它“张子阳”时,它又代表着“张子阳”这个值。

然后,我们可以在方法体内对这个name进行其他操作。

哎,这简直是废话么,刚学程序就知道了。

如果你再仔细想想,假如GreetPeople()方法可以接受一个参数变量,这个变量可以代表另一个方法,当我们给这个变量赋值 EnglishGreeting的时候,它代表着 EnglsihGreeting() 这个方法;当我们给它赋值ChineseGreeting 的时候,它又代表着ChineseGreeting()方法。

我们将这个参数变量命名为 MakeGreeting,那么不是可以如同给name 赋值时一样,在调用 GreetPeople()方法的时候,给这个MakeGreeting 参数也赋上值么(ChineseGreeting或者EnglsihGreeting等)?然后,我们在方法体内,也可以像使用别的参数一样使用MakeGreeting。

但是,由于MakeGreeting 代表着一个方法,它的使用方式应该和它被赋的方法(比如ChineseGreeting)是一样的,比如:MakeGreeting(name);好了,有了思路了,我们现在就来改改GreetPeople()方法,那么它应该是这个样子了:public void GreetPeople(string name, *** MakeGreeting){MakeGreeting(name);}注意到 *** ,这个位置通常放置的应该是参数的类型,但到目前为止,我们仅仅是想到应该有个可以代表方法的参数,并按这个思路去改写GreetPeople方法,现在就出现了一个大问题:这个代表着方法的MakeGreeting参数应该是什么类型的?NOTE:这里已不再需要枚举了,因为在给MakeGreeting赋值的时候动态地决定使用哪个方法,是ChineseGreeting 还是 EnglishGreeting,而在这个两个方法内部,已经对使用“morning”还是“早上好”作了区分。

聪明的你应该已经想到了,现在是委托该出场的时候了,但讲述委托之前,我们再看看MakeGreeting参数所能代表的 ChineseGreeting()和EnglishGreeting()方法的签名:public void EnglishGreeting(string name)public void ChineseGreeting(string name)如同name可以接受String类型的“true”和“1”,但不能接受bool类型的true和int类型的1一样。

MakeGreeting 的参数类型定义应该能够确定 MakeGreeting可以代表的方法种类,再进一步讲,就是MakeGreeting可以代表的方法的参数类型和返回类型。

于是,委托出现了:它定义了MakeGreeting参数所能代表的方法的种类,也就是MakeGreeting参数的类型。

NOTE:如果上面这句话比较绕口,我把它翻译成这样:string 定义了name参数所能代表的值的种类,也就是name 参数的类型。

本例中委托的定义:public delegate void GreetingDelegate(string name);可以与上面EnglishGreeting()方法的签名对比一下,除了加入了delegate关键字以外,其余的是不是完全一样?现在,让我们再次改动GreetPeople()方法,如下所示:public void GreetPeople(string name, GreetingDelegate MakeGreeting){MakeGreeting(name);}如你所见,委托GreetingDelegate出现的位置与 string相同,string是一个类型,那么GreetingDelegate应该也是一个类型,或者叫类(Class)。

但是委托的声明方式和类却完全不同,这是怎么一回事?实际上,委托在编译的时候确实会编译成类。

因为Delegate是一个类,所以在任何可以声明类的地方都可以声明委托。

更多的内容将在下面讲述,现在,请看看这个范例的完整代码:using System;using System.Collections.Generic;using System.Text;namespace Delegate {//定义委托,它定义了可以代表的方法的类型public delegate void GreetingDelegate(string name);class Program {private static void EnglishGreeting(string name) {Console.WriteLine("Morning, " + name);}private static void ChineseGreeting(string name) {Console.WriteLine("早上好, " + name);}//注意此方法,它接受一个GreetingDelegate类型的方法作为参数private static void GreetPeople(string name, GreetingDelegate MakeGreeting) {MakeGreeting(name);}static void Main(string[] args) {GreetPeople("Jimmy Zhang", EnglishGreeting);GreetPeople("张子阳", ChineseGreeting);Console.ReadKey();}}}输出如下:Morning, Jimmy Zhang早上好, 张子阳我们现在对委托做一个总结:委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

将方法绑定到委托看到这里,是不是有那么点如梦初醒的感觉?于是,你是不是在想:在上面的例子中,我不一定要直接在GreetPeople()方法中给 name参数赋值,我可以像这样使用变量:static void Main(string[] args) {string name1, name2;name1 = "Jimmy Zhang";name2 = "张子阳";GreetPeople(name1, EnglishGreeting);GreetPeople(name2, ChineseGreeting);Console.ReadKey();}而既然委托GreetingDelegate 和类型 string 的地位一样,都是定义了一种参数类型,那么,我是不是也可以这么使用委托?static void Main(string[] args) {GreetingDelegate delegate1, delegate2;delegate1 = EnglishGreeting;delegate2 = ChineseGreeting;GreetPeople("Jimmy Zhang", delegate1);GreetPeople("张子阳", delegate2);Console.ReadKey();}static void Main(string[] args) {GreetingDelegate delegate1;delegate1 = EnglishGreeting; // 先给委托类型的变量赋值delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法继续绑定方法// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法GreetPeople("Jimmy Zhang", delegate1);Console.ReadKey();}输出为:Morning, Jimmy Zhang早上好, Jimmy Zhang实际上,我们可以也可以绕过GreetPeople方法,通过委托来直接调用EnglishGreeting和ChineseGreeting:static void Main(string[] args) {GreetingDelegate delegate1;delegate1 = EnglishGreeting; // 先给委托类型的变量赋值delegate1 += ChineseGreeting; // 给此委托变量再绑定一个方法// 将先后调用 EnglishGreeting 与 ChineseGreeting 方法delegate1 ("Jimmy Zhang");Console.ReadKey();}NOTE:这在本例中是没有问题的,但回头看下上面GreetPeople()的定义,在它之中可以做一些对于EnglshihGreeting和ChineseGreeting来说都需要进行的工作,为了简便我做了省略。

相关文档
最新文档