【More Effective C#】?jī)H聲明非虛的事件
2010-10-13 08:17 空逸云 閱讀(440) 評(píng)論(0) 收藏 舉報(bào)C#除了可以聲明虛方法,屬性外,也可以聲明虛事件.但是并不建議使用虛事件.因?yàn)檫@常會(huì)帶來(lái)不可預(yù)測(cè)的Bug.我們定義了一個(gè)WorkerEngine類(lèi).它有一個(gè)虛事件.
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中.編譯器將會(huì)自動(dòng)創(chuàng)建私有字段,以及公共add和remove方法.
Private EventHandler<WorkerEventArgs>progressEvent;
Public virtual event EventHandler<WorkerEventArgs>OnOrigress
{
Add
{
progressEvent+=value;
}
Remove
{
progressEvent-=value;
}
}
由于該私有字段是編譯器生成的.所以你無(wú)法通過(guò)代碼訪(fǎng)問(wèn).而且,派生事件將隱藏基類(lèi)中的事件,派生類(lèi)所作的工作與原始版本完全一致.即基類(lèi)有一個(gè)自己的私有委托字段,派生類(lèi)自己也有一個(gè).兩個(gè)互不相干.
public class WorkerEngineDerived : WorkerEngineBase
{
protected override void SomeWork()
{
//...do some thing;
}
public override event EventHandler<WorkerEventArgs> OnProgress;
}
//調(diào)用
WorkerEngineDerived worker = new WorkerEngineDerived();
worker.DoLotsOfStuff();
結(jié)果并不與我們所想象的一致.
這里如前面所說(shuō).派生類(lèi)訪(fǎng)問(wèn)的事件是派生類(lèi)自己的事件.而非基類(lèi)的事件..如果對(duì)派生類(lèi)事件賦值.那么基類(lèi)中的隱藏私有字段將不會(huì)得到賦值.其他類(lèi)型訂閱到的是派生類(lèi)中的事件.解決的方案是基類(lèi)使用類(lèi)似字段方式聲明的事件.
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; }
}
}
子類(lèi)以屬性的方式重寫(xiě).那么結(jié)果很顯然便是我們所期望的
在創(chuàng)建虛事件時(shí),不要使用字段方式的語(yǔ)法,而應(yīng)該采用屬性式的語(yǔ)法.
我們也可以創(chuàng)建一個(gè)虛方法,在定義虛事件后調(diào)用該方法觸發(fā),所有的派生類(lèi)必須重寫(xiě)觸發(fā)事件的方法以及虛事件.
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
本文版權(quán)歸作者和博客園共有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文連接,否則保留追究法律責(zé)任的權(quán)利。
浙公網(wǎng)安備 33010602011771號(hào)