【More Effective C#】仅声明非虚的事件
2010-10-13 08:17 空逸云 阅读(433) 评论(0) 编辑 收藏 举报C#除了可以声明虚方法,属性外,也可以声明虚事件.但是并不建议使用虚事件.因为这常会带来不可预测的Bug.我们定义了一个WorkerEngine类.它有一个虚事件.
public abstract class WorkerEngineBase
{
public virtual event EventHandler<WorkerEventArgs> OnProgress;
public void DoLotsOfStuff()
{
OnProgress+=new EventHandler<WorkerEventArgs>(WorkerEngineBase_OnProgress);
WorkerEventArgs args = new WorkerEventArgs();
args.Percent = 2;
EventHandler<WorkerEventArgs> progHandler = OnProgress;
if (progHandler != null)
{
progHandler(this, args);
}
if (args.Cancel)
return;
}
void WorkerEngineBase_OnProgress(object sender, WorkerEventArgs e)
{
Console.WriteLine("WorkerEngineBase class event.");
}
protected abstract void SomeWork();
}
public class WorkerEventArgs : EventArgs
{
public int Percent { get; set; }
public bool Cancel { get; set; }
}
C#3.0中.编译器将会自动创建私有字段,以及公共add和remove方法.
Private EventHandler<WorkerEventArgs>progressEvent;
Public virtual event EventHandler<WorkerEventArgs>OnOrigress
{
Add
{
progressEvent+=value;
}
Remove
{
progressEvent-=value;
}
}
由于该私有字段是编译器生成的.所以你无法通过代码访问.而且,派生事件将隐藏基类中的事件,派生类所作的工作与原始版本完全一致.即基类有一个自己的私有委托字段,派生类自己也有一个.两个互不相干.
public class WorkerEngineDerived : WorkerEngineBase
{
protected override void SomeWork()
{
//...do some thing;
}
public override event EventHandler<WorkerEventArgs> OnProgress;
}
//调用
WorkerEngineDerived worker = new WorkerEngineDerived();
worker.DoLotsOfStuff();
结果并不与我们所想象的一致.
这里如前面所说.派生类访问的事件是派生类自己的事件.而非基类的事件..如果对派生类事件赋值.那么基类中的隐藏私有字段将不会得到赋值.其他类型订阅到的是派生类中的事件.解决的方案是基类使用类似字段方式声明的事件.
public class WorkerEngineDerived : WorkerEngineBase
{
protected override void SomeWork()
{
//...do some thing;
}
public override event EventHandler<WorkerEventArgs> OnProgress
{
add
{
base.OnProgress += value;
}
remove { base.OnProgress -= value; }
}
}
子类以属性的方式重写.那么结果很显然便是我们所期望的
在创建虚事件时,不要使用字段方式的语法,而应该采用属性式的语法.
我们也可以创建一个虚方法,在定义虚事件后调用该方法触发,所有的派生类必须重写触发事件的方法以及虚事件.
public abstract class WorkerEngineBase
{
public virtual event EventHandler<WorkerEventArgs> OnProgress;
protected virtual WorkerEventArgs RaiseEvent(WorkerEventArgs args)
{
EventHandler<WorkerEventArgs> progHandler = OnProgress;
if (progHandler != null)
progHandler(this, args);
return args;
}
public void DoLotsOfStuff()
{
OnProgress += new EventHandler<WorkerEventArgs>(WorkerEngineBase_OnProgress);
WorkerEventArgs args = new WorkerEventArgs();
args.Percent = 2;
RaiseEvent(args);
if (args.Cancel)
return;
}
void WorkerEngineBase_OnProgress(object sender, WorkerEventArgs e)
{
Console.WriteLine("WorkerEngineBase class event.");
}
protected abstract void SomeWork();
}
public class WorkerEngineDerived : WorkerEngineBase
{
protected override void SomeWork()
{
//...do some thing;
}
public override event EventHandler<WorkerEventArgs> OnProgress;
protected override WorkerEventArgs RaiseEvent(WorkerEventArgs args)
{
EventHandler<WorkerEventArgs> proghandler = OnProgress;
if (proghandler != null)
proghandler(this, args);
return args;
}
}
作者:空逸云
出处:http://kongyiyun.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
出处:http://kongyiyun.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
您的支持是我前进的动力,请猛击.: