![](/img/trans.png)
[英]Why events can't be used in the same way in derived classes as in the base class in C#?
[英]Raise Base Class Events in Derived Classes C#
我有一個基類DockedToolWindow:Form,還有許多從DockedToolWindow派生的類。 我有一個容器類,用於保存事件並將事件分配給DockedToolWindow對象,但是我想從子類中調用事件。
實際上,我對如何實現此MSDN網站告訴我的事情有疑問。 下面的這一節給了我這個問題:
// The event. Note that by using the generic EventHandler<T> event type
// we do not need to declare a separate delegate type.
public event EventHandler<ShapeEventArgs> ShapeChanged;
public abstract void Draw();
//The event-invoking method that derived classes can override.
protected virtual void OnShapeChanged(ShapeEventArgs e)
{
// Make a temporary copy of the event to avoid possibility of
// a race condition if the last subscriber unsubscribes
// immediately after the null check and before the event is raised.
EventHandler<ShapeEventArgs> handler = ShapeChanged;
if (handler != null)
{
handler(this, e);
}
}
當然,此示例可以編譯並運行,但是當我將“ ShapeChanged”替換為“ Move”(從Form派生而來的事件)時,錯誤地提示我不能在沒有+ =或-=的情況下在右側移動。 我還刪除了ShapeEventArgs通用標簽。
有人煽動為什么這行不通嗎? 類中聲明的事件與繼承的事件之間有什么區別?
您不能直接觸發基類事件。 這就是為什么必須將OnShapeChanged
方法protected
為private
方法的原因。
使用base.OnMove()代替。
從C#語言規范的10.7節(添加了重點):
在包含事件聲明的類或結構的程序文本中,某些事件可以像fields一樣使用 。 要以這種方式使用,事件不得為抽象事件或外部事件,並且不得明確包含event-accessor-declaration。 這樣的事件可以在允許字段的任何上下文中使用。 該字段包含一個委托(§15),該委托引用已添加到事件的事件處理程序的列表。 如果未添加事件處理程序,則該字段包含null。
因此,您不能將Move事件視為一個字段,原因是它以不同的類型(在本例中為您的超類)定義。 我同意@womp的推測,即設計師做出此選擇是為了防止意外出現在活動中。 允許無關的類型(不是從聲明事件的類型派生的類型)執行此操作顯然很糟糕,但是即使對於派生類型,也可能不希望這樣做。 他們可能必須包含語法,以允許將事件聲明設為private
或protected
字段樣式使用的保護,因此我的猜測是他們選擇完全禁止這樣做。
區別在於范圍。 在您的類內部,您可以控制事件委托的處理方式,但是,您的類無法控制基類的工作。 它可能會對事件及其處理程序進行一些瘋狂的幕后操作。 如果您只是“重新分配”了Move事件,則將清除該事件的多播委托列表。
我猜想他們對此施加了編譯器限制,因為這是一種非常不安全的做法,並且實際上將使任何后代類都有能力破壞其父級的事件模型。
您只需要在定義事件本身的類中發布的代碼。 所有派生類都應直接調用OnShapeChanged()或OnMove(),而不進行復制等操作,因此,您根本不應在類中編寫該代碼(因為Move事件是在基類中定義的)。
如果確實需要在派生類中進行某種處理(也許您需要弄弄集合類?),則可以覆蓋虛擬的OnXXX調用,並在調用base.OnXXX()之前進行填充。 在MSDN文章中,Circle類對應於您的DockedToolWindow類。 您的派生類應該可以使用相同的模式。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.