none
為何無法在子類別中呼叫母類別的事件 RRS feed

  • 問題

  • 大家好:

        小弟寫了一支程式。母類別有一個事件,本身可以呼叫它。但子類別無法呼叫。

    一編譯的話,母類別的成員函式 DoOneThing 可通過編譯,但是子類別的 DoSomething 

    會出現錯誤訊息  事件 'ConsoleApplication1.DataContainer.OnDeleteDataGridResult' 只能出現在 += 或 -= 的左邊 (除非從型別 'ConsoleApplication1.DataContainer' 中使用)

    其實有想到變通的方法,就是在 DoSomething 中去呼叫母類別的 DoOneThing。只是好奇為何有上面這樣的限制?

    照理說OnDeleteDataGridResult 也算是子類別的成員,為何無法直接使用它呢?不知大家有何看法。

     

    namespace ConsoleApplication1

    {

        public delegate void DataResultHandler(Boolean result);

        class DataContainer

        {

            public event DataResultHandler OnDeleteDataGridResult = null;

     

            public void DoOneThing()

            {

                if (OnDeleteDataGridResult != null) OnDeleteDataGridResult(true);

            }

        }

     

        class DataOperator : DataContainer

        {

            public void DoSomething()

            {

                if (OnDeleteDataGridResult != null) OnDeleteDataGridResult(true);

            }

        }

    }

    2010年7月5日 上午 02:55

解答

  • 宣告一個Event,在compile的時候,compiler會自動產生一個private的變數,

    例如宣告了一個Event如下:

    public event EventHandler MyEvent

    則compile後會產生如下的程式碼:

    private EventHandler _myEvent;

     

    public event EventHandler MyEvent

    {

        add

        {

            lock (this)

            {

                _myEvent += value;

            }

        }

        remove

        {

            lock (this)

            {

                _myEvent -= value;

            }

        }        

    }

     

    由於有個private的變數,所以只能由base class本身存取. 這裡有對delegate&event比較詳細的解說.

    在MSDN上,這個問題的建議解決方法是在base class裡宣告一個protected virtual method,再由derived

    class去overriding,以間接達到invoke base class event.

    • 已標示為解答 JoeSeom 2010年7月5日 上午 03:52
    2010年7月5日 上午 03:43

所有回覆

  • 請參閱MSDN 文件庫

    [event (C# 參考) ]

    其中有以下說明:

    事件是特殊種類的多點傳送委派,只能從宣告它們的類別或結構 (Struct) 內叫用 (即 Publisher 類別)。如果其他類別或結構訂閱該事件,則當 Publisher 類別引發該事件時,會叫用它們的事件處理常式方法。如需詳細資訊與程式碼範例,請參閱事 件 (C# 程式設計手冊) 委 派 (C# 程式設計手冊)


    以下是簽名檔, 請勿沒事對號入座
    MSDN 文件庫很重要
    回應幫助你的人是一種禮貌, 良好的禮貌有助於激發大家對你問題回應的熱情
    進步的人會找尋自己程式中的缺點,半桶水則把自己程式的錯誤推到不相干事物的身上
    2010年7月5日 上午 03:23
    版主
  • 您可以考慮將子類別寫成這樣:

    class DataOperator : DataContainer

        {

            public void DoSomething()

            {

                DoOneThing();

            }

        }

    2010年7月5日 上午 03:35
  • 宣告一個Event,在compile的時候,compiler會自動產生一個private的變數,

    例如宣告了一個Event如下:

    public event EventHandler MyEvent

    則compile後會產生如下的程式碼:

    private EventHandler _myEvent;

     

    public event EventHandler MyEvent

    {

        add

        {

            lock (this)

            {

                _myEvent += value;

            }

        }

        remove

        {

            lock (this)

            {

                _myEvent -= value;

            }

        }        

    }

     

    由於有個private的變數,所以只能由base class本身存取. 這裡有對delegate&event比較詳細的解說.

    在MSDN上,這個問題的建議解決方法是在base class裡宣告一個protected virtual method,再由derived

    class去overriding,以間接達到invoke base class event.

    • 已標示為解答 JoeSeom 2010年7月5日 上午 03:52
    2010年7月5日 上午 03:43
  • 小弟參閱了 c# 參考中的事件,在衍生類別中引發基底類別事件

    Bill Chung 您說得對,事件是一種委派 (Delegate) 的特殊型別,只能從宣告事件的類別中予以叫用 (Invoke)

    看來若要引發基底類別的事件,得透過基底類別的成員函式,不能在衍生類別直接引發。

    謝謝您的回覆。

    2010年7月5日 上午 03:51
  • 原來是因為這個 private 變數的關係,小弟終於了解前因後果了。

    我有找到您說的那篇文章 在衍生類別中引發基底類別事件

    謝謝 Horus Liu 的解說。

    2010年7月5日 上午 03:55