簡體   English   中英

更改參數類時無法覆蓋事件處理程序

[英]Can't override an event handler when changing the argument class

我正在嘗試覆蓋事件處理程序。 正常工作,除非當我也想覆蓋參數類時。 這是強制轉換為枚舉所必需的。

代碼顯示問題

public abstract class Base
{
    public class Args : System.EventArgs
    {
        public System.String arg { get; }
        public Args(System.String Iarg)
            : base()
        {
            arg = Iarg;
        }
    }
    public delegate void Handler(Args e);
    public abstract event Handler changed;
}
public class Sub_OK : Base
{
    public override event Handler changed;
}
public class Sub_Not_OK<TEnum> : Base
{
    new public class Args : System.EventArgs
    {
        public TEnum value { get; }
        public Args(TEnum Ivalue) { value = Ivalue; }
    }

    new public delegate void Handler(Args e);
    new public event Handler changed; // Error here
    //public override event Handler changed; // And error here
    //Including the next 2 lines compiles, but changed_2 can't be used in generic code.
    //public event Handler changed_2;
    //public override event Base.Handler changed;
}

嘗試過雜項。 new和override的組合,但無法使其編譯。

嘗試這種“新的公共類Args:Base.Args”無濟於事。

我得到這些錯誤:

Error CS0534 'Sub_Not_OK<TEnum>' does not implement inherited abstract member 'Base.changed.add'.
Error CS0534 'Sub_Not_OK<TEnum>' does not implement inherited abstract member 'Base.changed.remove'.

順便說一句,我不明白為什么我沒有得到相同的Sub_OK錯誤,這可能與無法解決此問題有關。

附言 抱歉,行李標簽沒有包含問題的名稱。

如果我正確理解了您的問題,那么當前使您感到困惑的主要是,錯誤消息似乎在說一些同樣適用於Sub_OKSub_Not_OK<T> 也就是說,兩個類都沒有Base.changed.addBase.changed.remove方法,因此兩個類應具有相同的錯誤。

您“順便說一句”,但似乎這確實是您目前所堅持的部分。

答案是您誤認為Sub_OK沒有這些方法。

在類中聲明的每個 event必須同時具有addremove方法。 (這類似於屬性的getset方法。) Base.changed事件具有它們(這就是必須重寫它們的原因),而Sub_OK類具有它們(這就是為什么不生成錯誤)的原因。

在C#類中使用event關鍵字時,有兩個選擇。 您可以讓編譯器生成addremove方法,也可以自己實現它們。 在您的Base類和Sub_OK類中,您自己沒有實現這些方法,因此編譯器為您實現了這些方法。 在抽象Base類中,由於事件被聲明為abstract ,所以addremove方法也被聲明為,它們必須在非抽象派生類中被覆蓋。

Sub_OK ,它們是。 您已經聲明了一個非抽象事件,該事件重寫了Base.changed事件,並且沒有提供顯式的addremove方法,因此編譯器為您創建了它們,因此一切都很好。

Sub_Not_OK ,這些方法不存在。 它們不存在,因為您使用了new關鍵字來隱藏基類成員,並創建所有新成員。 Sub_Not_OK.changed事件與基類中聲明的事件完全不同的事件 ,並且不會覆蓋該事件。 實際上,新event甚至不是虛擬的。

當然,這些new成員是Sub_Not_OK唯一成員。 因為從定義上來說它們是完全新的成員,並且與基類成員不相關,並且由於Sub_Not_OK 沒有其他成員,所以在Sub_Not_OK沒有任何東西可以覆蓋基類的抽象成員也很明顯。 包括Base.changed.addBase.changed.remove方法。 因此,錯誤消息。


現在,除此之外,還不清楚您的總體目標是什么。 一個很好的Minimal,Complete和Verifiable代碼示例 ,其中包括一些示例,說明了您希望如何使用這些類。 但是,總而言之,我認為您將無法完全按照自己的意願去做。

C#沒有提供子類化事件的方法。 您已經嘗試通過添加new關鍵字來解決在重新聲明成員時收到的警告,但這並沒有改變聲明的內容。 這只是讓您明確選擇隱藏基類成員。 特別是,您仍在隱藏成員,而不是覆蓋它們。

如果您確實為派生類堅持使用強類型的事件處理程序,則需要為此提供某種機制。 最好的方法是簡單地聲明一個具有不同名稱的新事件。 隱藏基類成員幾乎總是一個非常糟糕的主意,因為這會使代碼難以理解。 受影響成員的每次使用都依賴於上下文,並且人類很難跟蹤上下文。

您可以對虛擬事件進行某些操作,這些事件可以被覆蓋,但是從您的問題尚不清楚您希望如何使用它。 在上面的代碼中,假設您可以重寫基成員,則從基事件args類派生事件args類,以便派生的Sub_Not_OK類可以以某種方式使用該派生事件args類引發事件,然后呢? 類型仍然必須匹配(即事件仍必須使用基本的Handler委托類型),因此可以通過基本事件args類引發事件。 如果傳遞了錯誤的類型,則期望派生事件args類的處理程序將必須具有一些后備功能(例如檢查類型並忽略事件)。

歸根結底,最好重新考慮選擇的路徑。 您的問題沒有包含足夠的信息來知道什么是更好的設計,而是包含了足夠的信息來強烈建議您需要其他更好的設計。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM