事件(Event)
- 其实质就是具有特殊签名的委托,事件处理的就是委托链表的方法
- 事件可以解决委托带来的“封装不完善”的问题:
由于delegate的目的是为了将其暴露在类的客户端进行方法的注册,因此必须是 public 的
但这样一来,在客户端就可以对其进行随意的函数绑定,严重破坏对象的封装性 - 对于事件,无论内部的委托类型是 public 还是 protected,它总是 private的;在类的外部,注册“+=”和注销“-=”的访问限定符与委托类型限定符一致
事件的具体描述:
事件是类在发生其关注的事情时用来提供通知的一种方式
牵涉到2个角色:
1. 事件发布者:这个对象维护状态信息,当发生改变时便触发一个事件,并通知所有的事件订阅者
2. 事件订阅者:可以注册感兴趣的事件,在发布者触发一个事件后自动执行这段代码
// 代码来自:http://www.cnblogs.com/wudiwushen/archive/2010/04/20/1703763.html
//发布者(Publiser)
public class Publisher
{
//声明一个出版的委托
public delegate void PublishEventHander();
//在委托的机制下我们建立一个出版事件
public event PublishEventHander OnPublish;
//事件必须要在方法里去触发,出版社发布新书方法
public void issue()
{
//如果有人注册了这个事件,也就是这个事件不是空
if (OnPublish != null)
{
Console.WriteLine("最新一期的《火影忍者》今天出版哦!");
OnPublish();
}
}
}
//Subscriber 订阅者,无赖小明
public class MrMing
{
//对事件感兴趣的事情,这里指对出版社的书感兴趣
public static void Receive()
{
Console.WriteLine("嘎嘎,我已经收到最新一期的《火影忍者》啦!!");
}
}
//Subscriber 订阅者,悲情人物小张
public class MrZhang
{
//对事件感兴趣的事情
public static void Receive()
{
Console.WriteLine("幼稚,这么大了,还看《火影忍者》,SB小明!");
}
}
class Story
{
public static void Main(string[] args)
{
//实例化一个出版社
Publisher publisher = new Publisher();
//给这个出火影忍者的事件注册感兴趣的订阅者,此例中是小明
publisher.OnPublish += new Publisher.PublishEventHander(MrMing.Receive);
//另一种事件注册方式
//publisher.OnPublish += MrMing.Receive;
//发布者在这里触发出版火影忍者的事件
publisher.issue();
Console.ReadKey();
}
}
事件的匿名
一般来说上面的 Receive 函数只是为了响应事件的调用,为了更简洁(不用去想方法名字),可以使用匿名的方式
class Story
{
public static void Main(string[] args)
{
Publisher publisher = new Publisher();
publisher.OnPublish += delegate{
// 实现 Receive 的逻辑
}; // 注意有个分号
publisher.issue();
Console.ReadKey();
}
}
Lambda
微软对C#的路线是: 委托 -> 匿名表达式 -> Lambda表达式
搬自文章《C# Lambda表达式》,对照下一个加法在三种方式下的实现
delegate int calculator(int x, int y); //委托类型
// 委托
public static int Adding(int x, int y)
{
return x + y;
}
static void Main()
{
calculator cal = new calculator(Adding);
int He = cal(1, 1);
Console.Write(He);
}
// 对委托类型的简化
// Action<T>
static void Main()
{
Action<int, int> cal = new Action<int, int>(Adding);
int he = cal(1, 1);
Console.Write(he);
}
// Func<T>
// 相较 Action,最后一个参数为输出参数
static void Main()
{
Func<int, int, void> cal = new Func<int, int>(Adding);
int he = cal(1, 1);
Console.Write(he);
}
// 对委托函数的简化
// 匿名
static void Main()
{
calculator cal = delegate(int num1,int num2)
{
return num1 + num2;
};
int he = cal(1, 1);
Console.Write(he);
}
// Lambda
static void Main()
{
calculator cal = (x, y) => x + y;
int he = cal(1, 1);
Console.Write(he);
}
可以看到Lambda的基本形式:(输入参数)=>表达式
- 只有1个参数时,可以省略括号:()=>、(x)=>、x=>、(x,y)=>
- 包含多个表达式时,使用“{}+;”:(x)=>{语句1;语句2;};
一般结合 Func 达到委托类型和委托函数的简化
static void Main(string[] args)
{
Func<int, int, bool> gwl = (p, j) =>
{
if (p + j == 10)
{
return true;
}
return false;
};
Console.WriteLine(gwl(5,5) + "");
Console.ReadKey();
}