1.代理
有些书上也称“委托”。
C#中取消了指针的概念。对指针恋恋不舍的程序员可以有两种解决方法:声明“非安全”(unsafe)代码段然后在其中使用指针或者使用C#的一个引用类型——“代理”(delegate)。“代理”相当与C中的函数指针原型,区别是C#是类型安全的。
“代理”(delegate)(代表、委托):“代理”是类型安全的并且完全面向对象的。
(1)在C#中,所有的代理都是从System.Delegate类派生的(delegate是System.Delegate的别名)。
(2)代理隐含具有sealed属性,即不能用来派生新的类型。
(3)代理最大的作用就是为类的事件绑定事件处理程序。
(4)在通过代理调用函数前,必须先检查代理是否为空(null),若非空,才能调用函数。
(5)在代理实例中可以封装静态的方法也可以封装实例方法。
(6)在创建代理实例时,需要传递将要映射的方法或其他代理实例以指明代理将要封装的函数原型(.NET中称为方法签名:signature)。注意,如果映射的是静态方法,传递的参数应该是类名.方法名,如果映射的是实例方法,传递的参数应该是实例名.方法名。
(7)只有当两个代理实例所映射的方法以及该方法所属的对象都相同时,才认为它们是想等的(从函数地址考虑)。
(8)多个代理实例可以形成一个代理链,System.Delegate中定义了用来维护代理链的静态方法Combion,Remove,分别向代理链中添加代理实例和删除代理实例。
(9)代理的定义必须放在任何类的外面,如delegate int MyDelegate();而在类的方法中调用MyDelegate d = new MyDelegate(MyClass.MyMethod);来实例化自定义代理的实例。
实现一个代理:
(1)定义代理:delegate int Mydelegate(String args);
(2)定义要封装的方法:send(){}
(3)实例化代理:Mydelegate Md = new Mydelegate(send);
(4)引用代理:int i=My("我是代理");
2.事件(event):
任何编写过图形用户界面(GUI)软件的开发人员都熟悉事件处理编程,当用户与GUI控制进行交互时(例如点击表格上的按钮),作为上述事件的反应,就会执行一个或多个方法。没有用户的参与,事件也可能执行。事件处理程序是对象的方法,是根据应用程序中发生的事件而执行的。触发事件的对象称作发送者(sender),捕获事件并且做出响应的对象称作接收者(receiver),一个事件可以存在多个接受者。
(1)事件与代理的关系:
C#中的事件处理实际上是一种具有特殊签名的delegate,C#中的事件处理实际上是一种具有特殊签名的delegate,象下面这个样子:如下面这个样子:delegate public void MyEventHandler(object sender ,MyEventArgs e);
参数解释:
sender:代表事件发送者。
e:是事件参数类。
MyEventArgs:是自定义的事件参数类,所有的事件参数类都必须从System.EventArgs类派生。
(2)实现:
- 定义delegate对象类型,它有两个参数,第一个参数是事件发送者对象,第二个参数是事件参数类对象。
- 定义事件参数类,此类应当从System.EventArgs类派生。如果事件不带参数,这一步可以省略。
- 定义事件处理方法,它应当与delegate对象具有相同的参数和返回值类型。
- 用event关键字定义事件对象,它同时也是一个delegate对象。
- 用+=操作符添加事件到事件队列中(-=操作符能够将事件从队列中删除)。
- 在需要触发事件的地方用调用delegate的方式写事件触发方法。一般来说,此方法应为protected访问限制,既不能以public方式调用,但可以被子类继承。名字是可以是OnEventName。
- 在适当的地方调用事件触发方法触发事件。
(3)例子:
比如说一个公司(场景),你是老板,手下有两个员工,小张和小王。
你命令小王,如果小张玩游戏,则小王扣去小张1000元钱。
这就是现实中的委托。
实际上,在写程序中,程序员就是老板,小张和小王就是两个对象。小张玩游戏是一个方法,小张还有一个游戏事件,他玩游戏激发这个事件。而小王就是事件处理对象,他负责把小张的钱扣除1000。
定义5个类:事件触发者(小张),事件处理者(小王),事件参数类 ,事件的代理 ,发生事件的场景(主类)。
事件代理:
using System;
/// <summary>
/// MyEventHandler 的摘要说明
/// </summary>
public delegate void MyEventHandler(object sender,MyEventArgs e);
事件参数类:
using System;
/// <summary>
/// 事件参数类
/// </summary>
public class MyEventArgs:System.EventArgs
{
public String MyEventArgData;
}
事件的触发者:
using System;
/// <summary>
/// MyEventTrigger 事件的触发者
/// </summary>
public class MyEventTrigger
{
/// <summary>
/// 自定义事件
/// </summary>
public event MyEventHandler MyEvent;
/// <summary>
/// 事件触发方法
/// </summary>
public int money = 10000;
protected MyEventArgs e = new MyEventArgs();
protected void OnMyEvent()
{
if (MyEvent != null)
{
MyEvent(this, e);
}
}
public void playgame()
{
e.MyEventArgData = "小张:我开始玩游戏了。。。。";
this.OnMyEvent();
}
}
事件的处理者:
using System;
/// <summary>
/// 事件处理程序
/// </summary>
public class MyEventHandlerProcedures
{
/// <summary>
/// 用于处理事件的方法
/// </summary>
/// <param name="sender">事件发送者</param>
/// <param name="e">事件参数</param>
public void OnEventHandler(object sender, MyEventArgs e)
{
Console.WriteLine(e.MyEventArgData.ToString());
Console.WriteLine("小王:好小子上班玩游戏,看看你有多少钱");
MyEventTrigger 小张 = (MyEventTrigger) sender;
Console.WriteLine("小张的钱:" + 小张.money);
Console.WriteLine("开始扣钱.......");
System.Threading.Thread.Sleep(1000);
Console.WriteLine("扣钱完成");
小张.money = 小张.money-1000;
Console.WriteLine("小张仅剩下" + 小张.money + "看你以后还敢不敢玩游戏");
}
}
发生事件的场景(主类):
using System;
/// <summary>
/// MyEventSence 的摘要说明
/// </summary>
public class MyEventSence
{
public static void Main(String[] args)
{
Console.WriteLine("场景开始了.... ");
//先创建小张和小王
MyEventTrigger 小张 = new MyEventTrigger();
MyEventHandlerProcedures 小王 = new MyEventHandlerProcedures();
//现在叫小王监视小张是否有玩游戏
小张.MyEvent += new MyEventHandler(小王.OnEventHandler);
//此时小张开始玩游戏了
小张.playgame();
Console.WriteLine("场景结束.... ");
Console.ReadLine();
}
}
程序结果: