C#里事件和委托有啥区别啊??
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#里事件和委托有啥区别啊??相关的知识,希望对你有一定的参考价值。
一 、使用位置不同
事件只能在本类型内部“触发”,委托不管在本类型内部还是外部都可以“调用”。
二、使用符号不同
在类的外部,事件只能用“+=”和“-=”去订阅/取消订阅,如果是委托的话还可以使用“=”。
扩展资料:
1、C#中事件机制的工作原理:
(1)将实际应用中需通过事件机制解决的问题对象注册到相应的事件处理程序上,表示今后当该对象的状态发生变化时,该对象有权使用它注册的事件处理程序。
(2)当事件发生时,触发事件的对象就会调用该对象所有已注册的事件处理程序。
2、事件简介
触发事件的对象称为事件发送者;接收事件的对象称为事件接收者。事件就是用户对窗口上各种组件的操作。
使用事件机制可以实现:当类对象的某个状态发生变化时,系统将会通过某种途径调用类中的有关处理这个事件的方法或者触发控件事件的对象就会调用该控件所有已注册的事件处理程序等。
在.net框架中,事件是将事件发送者(触发事件的对象)与事件接受者(处理事件的方法)相关联的一种代理类,即事件机制是通过代理类来实现的。当一个事件被触发时,由该事件的代理来通知(调用)处理该事件的相应方法。
参考技术A委托的本质,是一个类,而事件,是委托这个类的一个私有变量加上两个公有方法(事件的+=和-=这两个公有方法,和委托实例的+=和-=功能上非常像,但并不是同一个东西),这是本质区别。
打个比方,string 也是一个类,而string s = "a",这个s是string这个类的一个变量(略有不恰当,为了方便直观理解,那么,委托是和string这个类同等的地位,而事件,是和s这个变量同等的地位)。
public delegate void myDel();相当于你创建了一个myDel的类,所以委托可以在任何地方创建,类需要实例化,所以委托需要实例化,要myDel m = ……;
申明一个事件 public event myDel myEvent;
事件myEvent类似于是一个myDel类型的一个变量,因为是变量,所以事件只能在类里面申明,不需要实例化,有点类似于上面的那个m。
既然myEvent(类似)和变量m都是myDel类型的一个变量,为什么还要弄一个事件这种东西出来,变量m不就可以实现事件的需求(监听,广播)吗?这里牵涉到了面向对象的一些设计理念,事件可以理解为委托实例m的一个约束版。
第一:委托实例m,哪里都可以用“+=”,“-=”,“=”三种方式,事件myEvent也可以用“+=”,“-=”,“=”三种方式,但是,事件的“=”必须要在申明他的类里面,才能用,外部,不能用,外部只需要关注注册“+=”和注销“-=”即可。因为外部如果可以用“=”,就会覆盖原有的其他注册进来的方法,这表明不安全,违背了封装性,外部的监听者,你只能管好自己是否监听,而不能因为你的监听误操作(“=”),覆盖了其他的未知监听者,所以在外部事件不允许用“=”。
第二:委托实例m,可以在任何地方调用,而事件myEvent,只能在申明他的类里面调用。这种限制,也是从面向对象的理念考虑。假设某个类(Class A)里面有一个事件,当这个类(Class A)的里面的某某属性(int b)发生了变化,然后发出通知,告诉所有的监听者。那么这个属性b,变没变,什么时候变,只能由A这个类自己知道,自己决定,自己触发,外部的任何类,无权过问,而委托的实例可以在任何地方调用,不符合这种封装性。
事件就是把委托实例的所有权利,都留给申明他的类,而只开放委托实例的注册和注销功能,给外部类。
事件最常用的场景,是用于广播变化给监听者,委托最常用的场景,是用于将方法当做参数进行传递(当然,委托也可以达到和事件一样的广播效果,不过没有事件那么安全)
事件可以理解为现实生活中发生的各种事情,例如老板拿了一堆文件放到秘书办公桌上,对秘书说帮我处理完这写报表,这就形成了一个委托,老板委托秘书帮他完成一份工作,
事实这份工作他也许已经早在以前就教给秘书怎么做了,但这次他还是交给秘书做尽管他自己可以做否则他请秘书而不干活就不如养一条人见人爱见谁跟谁跑的金毛啦,代码表示一下:
using System;
public class SamplesDelegate
public delegate String myMessionDelegate( string myFile );
public class mySampleClass
public String myWordFile( string myFile )
if ( myFile == "会议报告" )
return( "修改错别字并润色一下" );
if ( myInt == "项目调研" )
return( "修改错别字并转发给项目经理" );
return ( "修改错别字" );
public static String myFileSign ( string myFile )
if ( myFile ="会议报告" )
return( "会议" );
if ( myFile ="项目调研" )
return( "项目" );
return ( "一般文件" );
public static void Main()
mySampleClass mySC = new mySampleClass();
myMessionDelegate myD1 = new myMessionDelegate( mySC.myWordFile);
myMessionDelegate myD2 = new myMessionDelegate( mySampleClass.myFileSign );
Console.WriteLine( "0 修改方法 1; 类型\"2\".", "会议报告", myD1( "会议报告"), myD2( "会议报告" ) );
Console.WriteLine( "0 修改方法 1; 类型\"2\".", "项目调研", myD1( "项目调研"), myD2( "项目调研" ) );
Console.WriteLine( "0 修改方法 1; 类型\"2\".", "一般文件", myD1( "一般文件" ), myD2( "一般文件" ) );
*/
秘书接到文件后 判断文件类型 并 回忆 老板交给他的处理方法并进行 处理
-------------------------------------------
using System;
namespace 委托
delegate int NumOpe(int a,int b); //委托声明
class Class1
static void Main(string[] args)
Class1 c1 = new Class1();
NumOpe p1 = new NumOpe(c1.Add); //委托实例化
Console.WriteLine(p1(1,2)); //委托调用
Console.ReadLine();
private int Add(int num1,int num2)
return(num1+num2);
例中,委托NumOpe引用了方法Add。
委托声明了以后,就可以象类一样进行实例化,实例化时把要引用的方法(如:Add)做为参数,这样委托和方法就关联了起来,就可以用委托来引用方法了。
委托和所引用的方法必须保持一致:
1、参数个数、类型、顺序必须完全一致。
2、返回值必须一致。
在来一个
-------------------
using System;
namespace event_test
class DelegateEvent
public delegate void MyDelegate();
public event MyDelegate NotifyEveryOne;
public void Notify()
if(NotifyEveryOne != null)
System.Console.WriteLine("引发了事件!");
NotifyEveryOne(); //事件通知委托对象,委托对象调用实例化时作为参数的方法.
class clsA
public void DispMethodA()
System.Console.WriteLine("已经把事件NotifyEveryOne通知到ClassA!");
class clsB
public void DispMethodB()
System.Console.WriteLine("已经把事件NotifyEveryOne通知到ClassB!");
class clsTest
[STAThread]
static void Main(string[] args)
// 首先实例化一个事件源对象。
DelegateEvent eventSource = new DelegateEvent();
// 实例化事件的订户
clsA objA = new clsA();
clsB objB = new clsB();
// 使用委托把对象及其方法注册到事件中
eventSource.NotifyEveryOne +=new event_test.DelegateEvent.MyDelegate(objA.DispMethodA);
eventSource.NotifyEveryOne +=new event_test.DelegateEvent.MyDelegate(objB.DispMethodB);
eventSource.Notify();
参考技术C 事件就是一个狭义的委托,也就是事件是一个用于事件驱动模型的专用委托.
通俗的讲,委托你可以在客户代码中直接调用委托来激发委托指向的函数,而事件不可以,事件的触发只能由服务代码自己触发
也就是说在你的代码里委托你不但可以安排谁是它的调用函数,还可以直接调用它,而事件不能直接调用,只能通过某些操作触发
你可以理解事件就是一个或多个委托,此话应该有误的吧,事件可以有多个事件处理函数,委托同样也可以是个多播委托本回答被提问者采纳 参考技术D 事件是类在发生其被关注的事情时用来提供通知的一种方式。
使用事件,对象A可以将关于事件或已发生变化的信息通知其他对象B。
引发事件的对象称为事件发送方源。
捕获事件并对其作出响应的对象叫做事件接收方。
在事件通信中,发送方不知道哪个对象或方法将接收【处理】它引发的事件。故需要在发送方和接收方之间存在一个媒介【或类似
指针的机制】。.NET
Framework
定义了一个特殊的类型
(Delegate),该类型提供函数指针的功能。
事件使用委托来为触发时将调用的方法提供类型安全的封装。
这段话是我珍藏的,比较抽象。
为什么不能直接用委托代替事件?我个人觉得,在事件通讯这个模式下,这是规定好的:事件+=委托(方法)。如果按您的想法,直接委托+方法,那么接收方如何知道你到底干了什么事情,是双击了button,还是单击了一下窗体,又或者干了其他事情。首先没有方法知道,那么接收方调用哪个委托(方法)呢?
您好好看看刚开始的那段话,应该会有很大帮助。
C#事件是否委托
1.C#事件是不是委托?
2.为什么?
那到底是不是呢???
1.委托概述
委托是C#中新加入的一个类型,可以把它想作一个和Class类似的一种类型,和使用类相似,使用一个委托时,需要两个步骤,首先你要定义一个委托,就像是定义一个类一样;然后,你可以创建一个或多个该委托的实例。
定义一个委托的语法是这样的:
[public/protected/private] delegate returnType delegateName(paramtype param1,…)
这是我自己写的,看起来好像有点怪怪的,我来解释一下,private/protected/private是限定词,就不多说了,delegate是申明一个委托的关键词,returnType是一个返回类型,delegateName是一个你给委托起的名字,你可以写任何一个你喜欢的名字,paramtype param1…这个是参数列表。说了这么多可能看起来还是不是很好理解,我是这样认为的,实用点来讲,委托定义就是在一个函数定义中间加入一个delegate的关键词。它的作用类似于你申明一个类:
public class ClassName …
创建一个委托的实例:
[public/protected/private] delegateName deleInstanceName = new delegateName(MethodName)
这个类似于实例化一个类,public ClassName instancename = new ClassName(…),这里有个要注意的地方,即MethodName方法要和delegateName的签名一致。什么是签名一致,就是说MethodName的参数列表,返回值要分别和returnType、(paramtype param1,…)一致。举个例子来说明下:
public delegate string DelegateDemo(string name, int age);
比如我们如上定义了一个委托,就写法来说,其实就是在函数 string DelegateDemo(string name, int age)前面加了一个delegate的关键字,下面我们来用创建一个函数:
public string AgentDemo(string name, int age)
string rev = “”;
…
return rev;
这个函数是做参数传递给一个DelegateDemo实例的,接下来创建一个DelegateDemo的实例:
DelegateName instanceDemo = new DelegateName(AgentDemo);
这时要说到一致了,即AgentDemo和声明委托时的DelegateDemo(我们姑且将delegate去掉)这两个函数的返回值,参数列表要相同。终于说完了,不知道看的人明不明白。
接下来,我们可以使用这个委托了(调用一个委托),如下:
string name = “cshape”;
int age = 20;
instanceDemo(name, age);
当instanceDemo执行时,会执行AgentDemo函数,instanceDemo相当于C里的一个函数指针,现在这个指针指向AgentDemo的函数入口地址。
2.多点委托
前面提到的委托都只包含对一个方法的调用,如果需要调用多个方法,需要多次显示的调用这个委托,我们还有另的选择,我们可以让一个委托中包含多个方法,这样我们一次显示调用委托,就可以按照顺序连续的调用多个方法。看下面的例子:
public delegate void MultiDelegate(string name);
public void AgentDemo1(string str)
Console.WriteLine(str + “this is AgentDemo1\n”);
public void AgentDemo2(string s)
Console.WriteLine(s + “this is AgentDemo2\n”);
MultiDelegate multiDemo = new MultiDelegate(AgentDemo1);
multiDemo += new MultiDelegate(AgentDemo2);
multiDemo(“multiDemo test :”);
输出的结果应该是:
multiDemo test :this is AgentDemo1
mutliDemo test :this is AgentDemo2
可以看到我们一次显示的调用一个委托,它顺序的(按照你添加方法的顺序)执行了方法AgentDemo1和AgentDemo2。这里要注意的有几点:
● 委托支持 +=,-=这样的运算符,对应为添加或去掉一个方法
● 多点委托不可以定义有返回值,因为无法处理多个方法的返回值,所以如果要使用多点委托,应该用void,否则你的编译会返回一个错误
● 多点委托不建议你的参数列表中有OUT的类型,这样只会out最后一个方法的值,其他的值会丢失。
3.委托的理解
首先申明,这只是我举的一个例子,目的是帮助理解委托的过程,其中很多地方都经不起推敲,望大家知悉。言归正传,
你想要吃饭,
但是自己又不会做(委托方不知道实现细节),
你计划找个饭店,叫个回锅肉饭(定义了一个委托)
你决定找常去的那家叫做A的饭店(实例化一个委托)
你打电话给A饭店(委托调用)
A饭店给你做好了你的回锅肉饭(代理函数工作)
饭来了,真好。
4.委托的使用时机
当你需要把一个方法传送给其他方法时,可以考虑使用委托。好像不是很好理解,也可以这样说,当你确定要处理一件事,但又不能确定处理方法时,可以考虑用委托。其实单独的说委托的应用好像有点牵强,委托更多的是在事件中的应用。
5.一个委托的例子
我用两个类来做这个例子,一个类,我称它为委托方,一个类我称它为代理方,代码如下:
using System;
namespace Visen.Demo.Delegate
///<summary>
/// StartUp 委托演示中的程序入口,含委托方。
///</summary>
class StartUp
#region公用的方法
#region应用程序的主入口点。
///<summary>
///应用程序的主入口点。
///</summary>
[STAThread]
static void Main(string[] args)
Console.WriteLine("This is a delegate demo\n");
Visen.Demo.Delegate.Agent ag = new Agent();
//定义一个委托类型的对象
OutMessage singleDele = new OutMessage(ag.ShowMessage);
OutMessage deleStaticMeth = new OutMessage(Agent.SShowMessage);
//定义一个多点委托
OutMessage MultiDele = new OutMessage(ag.ShowMessage);
MultiDele += new OutMessage(Agent.SShowMessage);
singleDele(" delegate instance singleDele");
deleStaticMeth(" delegate instance deleStaticMeth");
MultiDele(" this is a MultiDele");
Console.Read();
#endregion应用程序的主入口点。
#endregion公用的方法
#region私用的字段
///<summary>
///定义一个委托类型
///</summary>
private delegate void OutMessage(string msg);
#endregion私有的字段
下面是代理方:
using System;
namespace Visen.Demo.Delegate
///<summary>
/// Agent 类为委托者的代理方,处理委托者委托的事务。
///</summary>
public class Agent
#region公用的方法
#region空的构造函数
///<summary>
///空的构造函数
///</summary>
public Agent()
#endregion空的构造函数
#region显示一条信息到控制台,一个类成员函数作为代理方
///<summary>
///显示一条信息到控制台,一个类成员函数作为代理方
///</summary>
///<param name="msg">显示内容</param>
public void ShowMessage(string msg)
Console.WriteLine("Method ShowMessage out:" + msg + "\n");
#endregion显示一条信息到控制台,一个类成员函数作为代理方
#region显示一条信息到控制台,一个类静态函数作为代理方
///<summary>
///显示一条信息到控制台,一个类静态函数作为代理方
///</summary>
///<param name="msg">显示信息</param>
public static void SShowMessage(string msg)
Console.WriteLine("static Method SShowMessage out:" + msg + "\n");
#endregion显示一条信息到控制台,一个类静态函数作为代理方
#endregion公用的方法
输出为:
This is a delegate demo
Method ShowMessage out: delegate instance singleDele
static Method SShowMessage out: delegate instance deleStaticMeth
Method ShowMessage out: this is a MultiDele
static Method SShowMessage out: this is a MultiDele
可见:方法函数可以是类成员函数,也可以是一个静态成员,只要和委托的签名相同就可以了。
有错的地方,请大家批评指正,谢谢!
回答者:zhangsilong - 江湖新秀 五级
参考资料:http://zhidao.baidu.com/question/39151329.html?si=1
参考技术A 首先给你解释一下委托是什么委托是一个类,这个类保存了一个对象和这个对象的一个方法,所以当你调用这个委托的时候就是调用保存的对象的哪个方法,委托的意义就是这个意思,把调用委托实际是委托给了一个对象的一个方法
因为委托是一个类,所以他是定义在类级别上的,也就是和类同级别的
事件是一种类的成员,他同方法,字段,属性是一个级别的,所以它定义在类的内部,你可以很容易区分开.
和字段,属性一样,事件也有事件类型,比如一个叫Name的属性是String类型的,那么一个叫MouseMove的事件他是一个叫EventHandler的委托类型的
现在我想你应该清楚委托实际上是一个类,仅仅是定义了一个委托的样子,而事件则是保存了委托的实例,因为他是成员本回答被提问者采纳 参考技术B 委托是一种特殊事件,在c++里有指针。在.net里有委托,说清楚一点,委托的作用就相当一指针。
事件有sender(发送方),但是事件不知道接受方是谁,这时候就需要委托去指向对应的接收方。 参考技术C 两种概念。事件的声明需要委托。 参考技术D 事件是委托的一种应用
以上是关于C#里事件和委托有啥区别啊??的主要内容,如果未能解决你的问题,请参考以下文章