上面代码中类似属性的public event GeneralEventHandler NumberChanged {add{...}remove{...}}语句便是事件访问器。使用了事件访问器以后,在DoSomething方法中便只能通过numberChanged委托变量来触发事件,而不能NumberChanged事件访问器(注意它们的大小写不同)触发,它只用于注册和取消注册。下面是代码输出:
Subscriber1 Invoked!
Return: Subscriber1
获得多个返回值与异常处理
现在假设我们想要获得多个订阅者的返回值,以List<string>的形式返回,该如何做呢?我们应该记得委托定义在编译时会生成一个继承自MulticastDelegate的类,而这个MulticastDelegate又继承自Delegate,在Delegate内部,维护了一个委托链表,链表上的每一个元素,为一个只包含一个目标方法的委托对象。而通过Delegate基类的GetInvocationList()静态方法,可以获得这个委托链表。随后我们遍历这个链表,通过链表中的每个委托对象来调用方法,这样就可以分别获得每个方法的返回值:
class Program4 {
static void Main(string[] args) {
Publishser pub = new Publishser();
Subscriber1 sub1 = new Subscriber1();
Subscriber2 sub2 = new Subscriber2();
Subscriber3 sub3 = new Subscriber3();
pub.NumberChanged += new DemoEventHandler(sub1.OnNumberChanged);
pub.NumberChanged += new DemoEventHandler(sub2.OnNumberChanged);
pub.NumberChanged += new DemoEventHandler(sub3.OnNumberChanged);
List<string> list = pub.DoSomething(); //调用方法,在方法内触发事件
foreach (string str in list) {
Console.WriteLine(str);
}
}
}
public delegate string DemoEventHandler(int num);
// 定义事件发布者
public class Publishser {
public event DemoEventHandler NumberChanged; // 声明一个事件
public List<string> DoSomething() {
// 做某些其他的事
List<string> strList = new List<string>();
if (NumberChanged == null) return strList;
// 获得委托数组
Delegate[] delArray = NumberChanged.GetInvocationList();
foreach (Delegate del in delArray) {
// 进行一个向下转换
DemoEventHandler method = (DemoEventHandler)del;
strList.Add(method(100)); // 调用方法并获取返回值
}
return strList;
}
}
// 定义事件订阅者
public class Subscriber1 {
public string OnNumberChanged(int num) {
Console.WriteLine("Subscriber1 invoked, number:{0}", num);
return "[Subscriber1 returned]";
}
}
public class Subscriber3 {与上面类同,略}
public class Subscriber3 {与上面类同,略}
如果运行上面的代码,可以得到这样的输出:
Subscriber1 invoked, number:100
Subscriber2 invoked, number:100
Subscriber3 invoked, number:100
[Subscriber1 returned]
[Subscriber2 returned]
[Subscriber3 returned]








