Action、Func、Predicate本质上都是委托
Action是无返回值的泛型委托
Action 表示无参,无返回值的委托
Action<int,string> 表示有传入参数int,string无返回值的委托
Func是有返回值的泛型委托
Func<int> 表示无参,返回值为int的委托
Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
Predicate 是返回bool型的谓语泛型委托
Predicate<int> 表示传入参数为int 返回bool的委托
Action示例: class Program
{
static Action A1;
static Action<string> A2;
static void Main(string[] args)
{
A1 = new Action(HelloWorld1);
A1();
A2 = new Action<string>(HelloWorld2);
A2("Jimmy");
//用Lambda表达式给委托赋值。
A2 = (string name) => { Console.WriteLine("你好,{0}!", name); };
A2("杨俊明");
//用匿名方法给委托赋值。
A2 = delegate(string name) { Console.WriteLine("我就是委托,{0} 你说对吗?", name); };
A2("菩提树下的杨过");
Console.Read();
}
static void HelloWorld1()
{
Console.WriteLine("Hello World!");
}
static void HelloWorld2(string name)
{
Console.WriteLine("Hello,{0}!", name);
}
}
Func示例:class ProgramObserver设计模式
{
static Func<string> F;
static Func<DateTime, string> F2;
static void Main(string[] args)
{
F = new Func<string>(HelloWorld1);
Console.WriteLine(F());
F2 = new Func<DateTime, string>(HelloWorld2);
Console.WriteLine(F2(DateTime.Now));
Console.Read();
}
static string HelloWorld1()
{
return "Hello World!";
}
static string HelloWorld2(DateTime time)
{
return string.Format("Hello World,the time is {0}.", time);
}
}
Observer设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖于它的对象会被自动告知并更新。
Observer模式主要包括如下两类对象:
Subject:被监视对象,它往往包含着其他对象所感兴趣的内容。在本范例中,热水器就是一个被监视对象,它的temprature字段就是其他对象感兴趣的内容,当这个字段的值大于95时时,会不断把数据发给监视它的对象。
Observer:监视者,它监视Subject,当Subject中的某件事发生的时候,会告知Observer,而Observer则会采取相应的行动。在本范例中,Observer有警报器和显示器,它们采取的行动分别是发出警报和显示水温。
范例:假设热水器由三部分组成:heater(热水器)、alarm(警报器)、display(显示器),它们来自于不同厂商并进行了组装。那么,应该是heater仅仅负责烧水,它不能发出警报也不能显示水温;在水烧开时由alarm发出警报、display显示水温。
怎么实现“水烧开时,heater通知alarm和display”呢。我们通过“事件”来实现。
using System;
namespace Delegate {
// 热水器
public class Heater {
private int temperature;
public delegate void BoilHandler(int param); //声明委托
public event BoilHandler BoilEvent; //声明事件
// 烧水
public void BoilWater() {
for (int i = 0; i <= 100; i++) {
temperature = i;
if (temperature > 95) {//水温大于95度时
if (BoilEvent != null) {//如果有对象注册
BoilEvent(temperature); //调用所有注册对象的方法。
}
}
}
}
}
// 警报器
public class Alarm {
public void MakeAlert(int param) {
Console.WriteLine("Alarm:嘀嘀嘀,水已经 {0} 度了:", param);
}
}
// 显示器
public class Display {
public static void ShowMsg(int param) {//静态方法
Console.WriteLine("Display:水快烧开了,当前温度:{0}度。", param);
}
}
class Program {
static void Main() {
Heater heater = new Heater();
Alarm alarm = new Alarm();
heater.BoilEvent += alarm.MakeAlert;//注册方法
heater.BoilEvent += (new Alarm()).MakeAlert; //给匿名对象注册方法
heater.BoilEvent += Display.ShowMsg; //注册静态方法
//烧水,水温大于95度时,会触发事件,自动调用注册过监听该事件的方法。
heater.BoilWater();
}
}
}
但这个范例不符合.net framework规范。符合.net规范的应该是
委托类型的名称都应该以EventHandler结束。委托的原型定义:有一个void返回值,并接受两个输入参数:一个Object 类型(代表了产生该事件的那个对象的引用),一个 EventArgs类型(事件产生时候传递的参数)。
这些不仅仅是为了编码规范,也使得程序有更大的灵活性。比如说,如果我们不光想获得热水器的温度,还想在Observer端 (警报器或者显示器)方法中获得它的生产日期、型号、价格,那么委托和方法的声明都会变得很麻烦,而如果我们将热水器的引用传给警报器的方法,就可以在方法中直接访问热水器了,也就不用在参数e中传递过多的信息了。