黑马程序员——深入理解C#的事件模型

 -------Java培训、Android培训、iOS培训、.Net培训 、期待与您交流! -------

深入理解C#的事件模型

(很久不玩C#了,文中可能出现一些误差,但不会影响对于事件模型的理解)

1,什么是委托?

由于很多教科书不区分委托类,和委托实例,这造成很多初学者的迷惑。广义的委托,同时指委托类,和委托实例。狭义的委托仅仅指委托实例。我在下面叙述的用词,会用,委托类,委托实例两个词来显示区分二者,童鞋们以后看到委托这两个字,应该根据上下文,推断他明确的含义是委托类,还是委托实例。也就是说,委托这个专业名词在不同的上下文环境中代表不同的含义。
2,什么是委托类?
委托类是继承自System.MulticastDelegate的一个类,他的继承结构如下。
System.Object 
  System.Delegate
    System.MulticastDelegate
3,怎么声明一个类,让他继承自System.MulticastDelegate?
这个问题对于理解继承,却不理解委托的同学可能感觉很迷惑,这太小儿科了,class  A:System.MulticastDelegate{....}不就OK了?,这不就是继承的语法吗?NO,NO,这也是童鞋难以理解委托的一个要点。微软规定,要声明一个继承自System.MulticastDelegate的类,在C#中,必须使用关键字delegate,不再使用class关键字,并且在使用delegate时,不能显示指明基类,因为这个关键字已经将基类固定了下来。形式如下
 public delegate void A(string name);

此处解下这句代码的本质含义:

(1),访问权限是public,童鞋们这个不用我解释吧,地球人都知道!,
(2),delegete 表示继承自基类System.MulticastDelegate(class 本质上表示继承自Object哦)
(3),这个A表示是继承自System.MulticastDelegate的一个类名,记住是类哦,A是类名,类名,类名。。。(不是实例名哦,童鞋们,别被微软的语法糖忽悠了,)
(4),其他部分是函数(方法)的签名
(5),整体意义如下,声明一个委托类,这个委托类的实例可以持有签名形型void method(string name)一样的方法(方法名可以不同,但是返回值,形参必须兼容)
4,什么是委托实例?
由委托类声明的对象称为委托实例
public delegate void A(string name);
class DeleMono
{
A a;
public static void DemoMethodS(string  str){   Console.WriteLine(str);     }
public static void DemoMethodI(int integer){   Console.WriteLine(integer);  }
 }
DeleMono mono;
//委托实例不需要显示用new来实例化;声明后就可以为他赋值,他的值可比较特别,他的值,是一个方法的引用(指针)
mono.a=DeleMono.DemoMethodS;//赋值不能带圆括号哦,否则就会执行函数了;赋值没有问题,这就是是我所说的,委托实例的值,是一个方法的引用(指针)的含义; 
//mono.a=DeleMono.DemoMethodI;编译错误,因为签名兼容,这个不需要我细细解释了吧。 
mono.a("Hello World!");
DemoMono.DemoMethods("Hello World!");
//以上两句将会完全等价,在后台他们调用的是同一个函数
OK,我们现在总结一下
委托类就是一个类,这个类的特殊之处是,他的实例是一个指向方法的变量”(我其实更喜欢使用函数指针来形容) 
5,什么是多播委托?
委托实例的特殊之处是,不只是它可以指向一个方法,他甚至可以同时指向多个方法(事实上在内部是有一个链表的,但是这个链表对程序猿不可视,我们只管用好了)  委托实例可以同时
指向多个方法的特性叫做多播委托,也可以理解为指向多个方法的委托实例,就是多播委托
public delegate void A(string name);
class DeleMono
{
A a;
public static void DemoMethodS1(string  str){   Console.WriteLine(str);     }
public static void DemoMethodS1(string  str){   Console.WriteLine(str);     }  
}
DeleMono mono;
mono.a=DeleMono.DemoMethodS1;
mono.a+=DeleMono.DemoMethod2;//注意哦,是+=哦,否则会覆盖先前的
mono.a("Hello World!");//这次这样调用,将会打印两遍Hello World!,一次委托实例的调用,将会调用他持有的所有方法;很简单吧;
6,什么是事件?事件本质上就是一种特殊委托实例,根本没有事件类的说法;
public delegate void SampleEventHandler(object sender, SampleEventArgs e);
public event SampleEventHandler SampleEvent;//定义一个委托实例,但是,因为这个定义多出来一个event关键字,此处要称为事件实例;本质上不要event关键字程序也完全没有影响,
event关键字可以认为是以一种约定,为了突出表示拥有它的类,会在特定时刻来使用调用一个特殊的委托;如果其他类也想在这个时刻进行某一操作,就可以把自己的方法赋值给他;可以看到事件实例的第一个形参是object,这样就能保证任何任何类的内部都可以声明事件实例了,这个形参默认就是代表激活事件的对象,(任何对象都可能激活事件,)第二个参数是事件参数,用户定义的事件参数类必须继承自EventArgs,只有这样才兼容。这种签名是事件特有的,也可以认为,只有具有这种签名的委托,才可以被event修饰
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值