C# 委托—事件访问器
此文在张子阳的 C#中的委托和事件(续) 的基础上修改而成,由于水平所限文中,文中错漏之处在所难免(特别是在措词方面),敬请回帖斧正,涕零感激。
委托变量和事件都可以供多个订阅者注册,如果委托定义了返回值,那么多个订阅者的方法都会向发布者返回数值,结果就是后面一个返回的方法值会覆盖前面一个的方法返回值.
例子:
{
static void Main(string[] args)
{
Publishser pu = new Publishser();
Subscriber1 s1 = new Subscriber1();
Subscriber2 s2 = new Subscriber2();
Subscriber3 s3 = new Subscriber3();
pu.Eventr += s1.Outer;
pu.Eventr += s2.Outer;
pu.Eventr += s3.Outer;//到此为止,有3个订阅者注册了Eventr事件,在下面触发事件的时候这三个订阅者会被依次执行,但最终的只会有一个返回值
pu.InvokeEventr();//触发事件
Console.ReadLine();
}
}
//定义委托
public delegate string Delegater();
//定义事件发布者
class Publishser
{
//定义事件
public event Delegater Eventr;
public void InvokeEventr()//触发事件
{
Delegater delegater = Eventr;
if (delegater != null)
Console.WriteLine(delegater());//输出结果
}
}
//定义事件订阅者
class Subscriber1
{
public string Outer()
{
Console.WriteLine("this is Subscriber1");
return "Subscriber1 Outer";
}
}
class Subscriber2
{
public string Outer()
{
Console.WriteLine("this is Subscriber2");
return "Subscriber2 Outer";
}
}
class Subscriber3
{
public string Outer()
{
Console.WriteLine("this is Subscriber3");
return "Subscriber3 Outer";
}
}
输出结果:
this is Subscriber1
this is Subscriber2
this is Subscriber3
Subscriber3 Outer
上面输出 this is Subscriber1, this is Subscriber2, this is Subscriber3 表示三个订阅者中的outer方法都执行了,而 输出的Subscriber3 Outer则代表Subscriber3的outer方法返回值覆盖了Subscriber1, Subscriber2的outer方法返回值,
为了避免上面的"值覆盖, 我们可能想限制只允许一个客户端注册。
方法如下:将事件声明为private的,然后提供两个方法来进行注册和取消注册
{
static void Main(string[] args)
{
Publishser pu = new Publishser();
Subscriber1 s1 = new Subscriber1();
Subscriber2 s2 = new Subscriber2();
Subscriber3 s3 = new Subscriber3();
pu.DelEventr(s1.Outer);//这里不会出错
pu.ResEventr(s2.Outer);//注册成功
pu.ResEventr(s3.Outer);//重新进行注册
pu.InvokeEventr();//触发事件
Console.ReadLine();
}
}
//定义委托
public delegate string Delegater();
//定义事件发布者
class Publishser
{
//定义事件
private event Delegater Eventr;
public void ResEventr(Delegater De)
{
Eventr = De;//注意这里没有使用+=,来实现只能注册一次
}
public void DelEventr(Delegater De)
{
Eventr -= De;//这里没有对De就行为空判断,因为即使没有注册过,不会影响程序的进行,不会抛出异常,不会有任何现象。
}
public void InvokeEventr()//触发事件
{
Delegater delegater = Eventr;
if (delegater != null)
Console.WriteLine(delegater());//输出结果
}
}
//定义事件订阅者
class Subscriber1
{
public string Outer()
{
Console.WriteLine("this is Subscriber1");
return "Subscriber1 Outer";
}
}
class Subscriber2
{
public string Outer()
{
Console.WriteLine("this is Subscriber2");
return "Subscriber2 Outer";
}
}
class Subscriber3
{
public string Outer()
{
Console.WriteLine("this is Subscriber3");
return "Subscriber3 Outer";
}
}
输出结果为:
this is Subscriber3
Subscriber3
此时应该注意到我们的实现方法已经类似于C#中的属性(在c#中在C#中通常一个属性对应一个类型成员,而在类型的外部对成员的操作全部通过属性来完成),我们变相的实现了。
恰恰C#提供了一种叫事件访问器(Event Accessor)用来封装委托变量。
实现方法:
class Delegater3
{
static void Main(string[] args)
{
Publishser pu = new Publishser();
Subscriber1 s1 = new Subscriber1();
Subscriber2 s2 = new Subscriber2();
Subscriber3 s3 = new Subscriber3();
pu.Eventr += s1.Outer;//注册s1
pu.Eventr -= s1.Outer;//移除s1
pu.Eventr += s2.Outer;//注册s2
pu.Eventr += s3.Outer;//注册s3,覆盖s2
pu.InvokeEventr();//触发事件
Console.ReadLine();
}
}
//定义委托
public delegate string Delegater();
//定义事件发布者
class Publishser
{
//定义委托变量
private Delegater eventr;
//定义事件
public event Delegater Eventr
{
add { eventr = value; }
remove { eventr -= value; }
}
public void InvokeEventr()//触发事件
{
Delegater delegater = eventr;
if (delegater != null)
Console.WriteLine(delegater());//输出结果
}
}
//定义事件订阅者
class Subscriber1
{
public string Outer()
{
Console.WriteLine("this is Subscriber1");
return "Subscriber1 Outer";
}
}
class Subscriber2
{
public string Outer()
{
Console.WriteLine("this is Subscriber2");
return "Subscriber2 Outer";
}
}
class Subscriber3
{
public string Outer()
{
Console.WriteLine("this is Subscriber3");
return "Subscriber3 Outer";
}
}
输出结果为:
this is Subscriber3
Subscriber3
注意:使用事件访问器后 只能通过委托变量来实现委托,因为不能通过事件访问器实现,事件访问器仅实现注册与反注册。