唯一看明白额委托与事件讲解

合集下载

委托和事件

委托和事件

联系方式shuofeng87@第九章委托和事件9.1委托回调函数是一种非常强大的编程特性,包括窗口过程、异步过程调用都是需要回调函数的。

在C、C++和Pasal中,回调函数是通过函数指针实现的,但是,函数指针只是一个内存地址,这个地址不带任何额外信息,比如函数期望收到的参数个数、参数类型、函数的返回值类型以及函数的调用约定,所以函数指针是非类型安全的。

因此,Java中为了保证程序的安全性,不提供任何具有指针函数功能的结构。

但是C#中提供这种结构,这就是类型安全的委托。

9.1.1委托的定义委托是由Delegate类派生的子类的实例,它可以封装引用的方法,使被引用的方法可以像数据一样作为参数被进行传递和回调。

图9_1_1类试图委托定义的语法形式例:要引用的方法如下public static void DelegateMethod(string message){System.Console.WriteLine(message);}第一步,确定将要引用方法的签名,声明一个委托类型例:public delegate void Del (string message);[访问修饰符] delegate 返回值类型委托类名(形参列表);注意:1形式:委托声明类似于方法的定义,但是没有方法体,在返回值类型前要加上delegate 关键字2委托的签名:就是委托声明中的返回值类型,形参类型和形参个数要与被引用的方法匹配。

(不必完全匹配,委托支持协变与逆变,后面将详细讲解)3 委托的声明其实就是一个类的定义,所以可以在定义类的任何地方定义委托。

第二步,实例化一个委托例:Del handler = DelegateMethod;委托类名委托名= 被引用的方法名;注意:1这里只能是被引用的方法名,不可以带(),因为handler的本质是一个对象,对其进行赋值只是将DelegateMethod的内存单元地址传入handler中。

委托和事件的区别

委托和事件的区别

委托和事件的区别(讲的很详细)--转委托和事件在 .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()方法,以适应新的需求。

委托和事件的区别

委托和事件的区别

委托和事件的区别(讲的很详细)--转委托和事件在 .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#中的委托是一种引用方法的类型,一旦为委托分配了方法,委托将与该方法具有完全相同的行为,委托方法的使用可以像其他任何方法一样具有参数和返回值。

委托对象能被传递给调用该方法引用的代码而无须知道哪个方法将在编译时被调用。

委托是函数的封装,它代表一“类”函数。

他们都符合一定的签名:拥有相同的参数列表、返回值类型。

同时委托也可以看作是对函数的抽象,是函数的“类”。

此时,委托实例代表一个具体的函数。

委托应该和类同属一个层面,使用起来也很象一个类。

我们先来看一个委托使用的实例:public delegate void PrintHandler(string str); // 声明委托类型public class PrintStr{public void CallPrint(string input){Console.WriteLine(input);}}static void Main(string[] args){PrintStr myPrinter = new PrintStr();PrintHandler myHandler = null;// 将委托链接到方法,来实例化委托myHandler += new PrintHandler(myPrinter.CallPrint);if (myHandler != null)myHandler("Hello World!"); // 调用委托,相当于匿名调用委托所链接的方法myHandler -= new PrintHandler(myPrinter.CallPrint);if (myHandler == null)Console.WriteLine("myHandler==null");Console.Read();}得到的结果为Hello World!myHandler==null二、委托的特点1、一个委托对象可以搭载多个方法。

C#中委托和事件的区别实例解析

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#事件与委托详解【精华多看看】Delegatedelegate是C#中的⼀种类型,它实际上是⼀个能够持有对某个⽅法的引⽤的类。

与其它的类不同,delegate类能够拥有⼀个签名(signature),并且它"只能持有与它的签名相匹配的⽅法的引⽤"。

它所实现的功能与C/C++中的函数指针⼗分相似。

它允许你传递⼀个类A的⽅法m给另⼀个类B的对象,使得类B的对象能够调⽤这个⽅法m。

但与函数指针相⽐,delegate有许多函数委托和事件在 .Net Framework中的应⽤⾮常⼴泛指针不具备的优点。

⾸先,函数指针只能指向静态函数,⽽delegate既可以引⽤静态函数,⼜可以引⽤⾮静态成员函数。

在引⽤⾮静态成员函数时,delegate不但保存了对此函数⼊⼝指针的引⽤,⽽且还保存了调⽤此函数的类实例的引⽤。

其次,与函数指针相⽐,delegate是⾯向对象、类型安全、可靠的受控(managed)对象。

也就是说,runtime能够保证delegate指向⼀个有效的⽅法,你⽆须担⼼delegate会指向⽆效地址或者越界地址。

实现⼀个delegate是很简单的,通过以下3个步骤即可实现⼀个delegate:1.声明⼀个delegate对象,它应当与你想要传递的⽅法具有相同的参数和返回值类型。

2.创建delegate对象,并"将你想要传递的函数作为参数传⼊"。

3.在要实现异步调⽤的地⽅,通过上⼀步创建的对象来调⽤⽅法。

using System;public class MyDelegateTest{// 步骤1,声明delegate对象public delegate void MyDelegate(string name);// 这是我们欲传递的⽅法,它与MyDelegate具有相同的参数和返回值类型public static void MyDelegateFunc(string name){Console.WriteLine("Hello, ", name);}public static void Main(){// 步骤2,创建delegate对象(实例??)MyDelegate md = new MyDelegate(MyDelegateTest.MyDelegateFunc);// 步骤3,调⽤delegatemd("sam1111");}}输出结果是:Hello, sam1111了解了delegate,下⾯我们来看看,在C#中对事件是如何处理的。

委托和事PPT课件

委托和事PPT课件

......
void Mul{int x,
7
int y)
郑宇军 人民邮电出版社 2009
7
委托和方法
委托封装方法
DualFunction fun1 = new DualFunction(Add); fun1(2,3); fun1 = new DualFunction(Sub);
fun
void Add{int x,
10
委托和方法
传递委托对象
▪ 作为方法参数 ▪ 作为方法返回值
11
郑宇军 人民邮电出版社 2009
11
委托和方法
Delegate类型
▪ DynamicInvoke
Fun1(2.5,2)
Fun1.DynamicIn voke(2.5,2)
▪ Combine/Remove
DualFunction fun3 = fun1 + fun2
DualFunction fun1 = delegate(int x, int y) {
Console.WriteLine("{0}+{1}={2}", x, y, x+y); }
13
郑宇军 人民邮电出版社 2009
13
匿名方法
外部变量
捕获外部变量 捕获外部变量
double a=2.5, b=2; DualFunction fun1 = delegate(int a, int b) {
a++; b++; } fun1(a,b); DualFunction fun2 = delegate(int a, int b) {
a++; b--; } fun2(a,b);

委托和事件——精选推荐

委托和事件——精选推荐

委托和事件⼀、委托1、什么是委托委托是⾯向对象的、类型安全的,是引⽤类型。

使⽤delegate关键字进⾏定义。

委托的本质就是⼀个类,继承⾃System.MulticastDelegate,⽽它⼜派⽣⾃System.Delegate。

⾥⾯内置了⼏个⽅法,可以在类的外⾯声明委托,也可以在类的内部声明委托。

对委托的使⽤:先定义,后声明和实例化委托,然后作为参数传递给⽅法。

1.1 定义委托下⾯是⼏种委托定义的例⼦:1using System;2using System.Collections.Generic;3using System.Linq;4using System.Text;5using System.Threading.Tasks;67namespace MyDelegateDemo8 {9// 也可以在类的外⾯定义委托10public delegate void NoReturnNoParaOutClass();1112public class MyDelegate13 {14// 声明⽆参数⽆返回值的泛型委托15public delegate void NoReturnNoPara<T>(T t);16// 声明⽆参数⽆返回值的委托17public delegate void NoReturnNoPara();18// 声明有参数⽆返回值的委托19public delegate void NoReturnWithPara(int x, int y);20// 声明⽆参数有返回值的委托21public delegate int WithReturnNoPara();22// 声明有参数有返回值的委托23public delegate string WithReturnWithPara(out int x,ref int y);24 }25 }1.2 声明并实例化委托实例化委托时参数传递的是⼀个⽅法,⽅法的签名必须和委托的签名⼀样(即⽅法的返回值类型、参数列表的参数类型都必须和定义的委托⼀致)。

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

一、在控制台下使用委托和事件
我们都知道,C#中有“接口”这个概念,所谓的“接口”就是定义一套标准,然后由实现类来具体实现其中的方法,所以说“接口,是一组类的抽象”。

同样道理,我们可以将“委托”理解为“方法的抽象”,也就是说定义一个方法的模板,至于这个方法具体是怎么样的,就由方法自己去实现。

我们知道接口的最大好处就是可以实现多态,同理,“委托”是可以实现方法的多态,当我们想调用某个具体方法的时候,我们不直接调用这个方法,而是去调用这个委托。

当然,我们必须在具体方法和委托之间建立某种关联。

下面我们来看例子。

首先,我们定义一个委托:
public delegate void SaySomething(string name);
这跟抽象方法的语法格式很相似,只是多了一个关键字delegate。

既然是对方法的一种抽象,那么我们最关注的当然就是方法的返回值以及方法的参数了。

所以上面红色的部分就是我们定义出来的一个规矩,如果某个方法想委托我去做事,那么请你遵循我的规矩,就是返回值为void,参数为一个字符串。

我们这个委托的含义是,当某个人来了,就向他说点东西。

好,既然我们已经定义了这个规矩,下面我们就定义具体的方法了。

public void SayHello(string name)
{
Console.WriteLine("Hello," + name + "!");
}
public void SayNiceToMeetYou(string name)
{
Console.WriteLine("Nice to meet you," + name + "!");
}
我们这里一共定义了两个方法,一个是向某人说Hello,另一个是向某人说Nice to meet you。

我们看到,这里定义的两个方法的返回值和参数跟我们前面定义的“委托”是一致的。

接下来,我们来看事件。

public event SaySomething come;
我们定义了一个事件,这个事件是“有人来了”,注意定义的时候我们使用event关键字,除此之外,我们还加上了前面定义的“委托”的名字。

这个意思是说,我这个事件只会跟“SaySomething”打交道,并且,当我这个事件发生的时候,我会通知关注我的这些“委托”(再由这些“委托”去调用具体的方法)。

我们来定义一个测试方法:
public void test() {
SaySomethingsayhello = new SaySomething(SayHello);
SaySomethingsaynice = new SaySomething(SayNiceToMeetYou);
come += sayhello;
come += saynice;
come("张三");
}
方法体中的前面两行是用来实例化委托,注意我们用到了new关键字,就好像实例化一个类一样,然后传入一个参数,但这个参数不是string类型、也不是int类型,而是一个方法名。

再下面两行就是将委托加到事件上,意思是说,如果你这个事件发生了,就告诉我一声。

可以通过“+=”来将n个委托实例加到某个事件上,一旦这个事件发生,所有的这些委托实例都会得到通知。

最后一行是触发一个事件,注意我们是直接用一个事件名,然后跟一个参数,这又跟“委托”中定义的那个规矩一致(即,要有一个string类型的参数)。

最后运行一下
static void Main(string[] args)
{
Program program = new Program();
program.test();
Console.Read();
}
我们回过头来再看一下“事件”的定义:
public event SaySomething come;
这里已经指出了“委托”的名字,所以,我们可以直接将方法加到事件上,而省略“委托”的实例化过程,因此上面的test()方法可以简单写为:
public void test() {
come += SayHello;
come += SayNiceToMeetYou;
come("张三");
}。

相关文档
最新文档