Domanda

Ho una classe base DockedToolWindow :Forma, e molte classi che derivano da DockedToolWindow.Ho una classe contenitore che contiene e assegna eventi DockedToolWindow oggetti, ma voglio richiamare gli eventi del bambino in classe.

Ho una domanda su come implementare questa cosa Sito web MSDN mi dice di fare.Questa sezione mi sta dando il problema:

    // 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);
        }
    }

Sicuro che questo esempio compila e funziona, ma quando sostituire "ShapeChanged" con "Move" (un evento che ho acquisito da derivanti dalla Forma), errori dicendo: - non posso Spostare sul lato destro senza += o -=.Ho anche rimosso il ShapeEventArgs generico tag.

Qualsiasi incitare sul perché non funziona?Qual è la differenza tra un evento ha dichiarato all'interno della classe e uno che è ereditaria?

È stato utile?

Soluzione

Non si può sparare direttamente eventi di livello base. Questo è esattamente il motivo per cui si doveva fare il metodo di OnShapeChanged protected invece di private.

base.OnMove () .

Altri suggerimenti

Dal linguaggio C# spec, sezione 10.7 (enfasi aggiunta):

All'interno del programma di testo della classe o della struttura che contiene la dichiarazione di un evento, alcuni eventi possono essere utilizzati come campi.Per essere utilizzato in questo modo, un evento non deve essere astratta o esterno, e non deve includere esplicitamente evento-accessor-dichiarazioni.Tale evento può essere utilizzato in qualsiasi contesto, che permette a un campo.Il campo contiene un delegato (§15), che si riferisce all'elenco dei gestori di eventi che sono stati aggiunti all'evento.Se non gestori di eventi sono stati aggiunti, il campo contiene il valore null.

Così, la ragione non è possibile trattare l'evento Move come un campo in cui è definito un tipo diverso (in questo caso, superclasse).Sono d'accordo con @womp è la speculazione che i progettisti hanno fatto questa scelta per evitare indesiderati monkeying con l'evento.Sembra ovviamente un male per consentire estranei tipi di tipi non deriva dal tipo di dichiarare l'evento), ma anche per tipi derivati, potrebbe non essere desiderabile.Probabilmente avrebbe dovuto comprendere la sintassi per consentire la dichiarazione di evento per essere fatto private o protected rispetto al campo di stile di utilizzo, quindi la mia ipotesi è che hanno optato per solo impedire del tutto.

La differenza è ambito. All'interno della vostra classe, è possibile controllare come i vostri delegati degli eventi vengono gestiti, tuttavia, la classe non può controllare quello che la classe base sta facendo. Si potrebbe fare qualche pazzo cose dietro le quinte con l'evento ed i suoi gestori. Se semplicemente "riassegnato" l'evento Sposta, si sarebbe cancellare la lista delegato multicast per l'evento.

Sto indovinando hanno messo una restrizione compilatore su questo perché la sua una pratica molto pericolosa, e sarebbe in sostanza dare alcuna classe discendente la capacità di distruggere il modello di eventi del suo genitore.

È necessario solo il codice che avete inviato nella classe in cui è definito l'evento stesso. Tutte le classi derivate devono semplicemente chiamare OnShapeChanged () o OnMove () direttamente, senza la copia, ecc, in modo da non dovrebbe essere iscritto che il codice a tutti nelle classi (dal momento che l'evento Move è definito nella base).

Se si ha bisogno di fare una sorta di trasformazione nella classe derivata (forse avete bisogno di giocherellare con la classe collezione?), Si ignora la chiamata onxxx virtuale e fare roba prima di chiamare base.OnXXX (). Nel articolo di MSDN, la classe Circle corrisponde alla classe DockedToolWindow. Lo stesso modello dovrebbe essere disponibile per le vostre classi derivate.

scroll top