2010-06-17 13 views
5

Perché non posso utilizzare l'evento dichiarato in Base da Sub?Utilizzare l'evento e delegare nella sottoclasse

class Program 
{ 
    static void Main(string[] args) 
    { 
     Sub sub = new Sub(); 
     sub.log += new Base.logEvent(sub_log); 
     sub.go(); 
    } 

    static void sub_log(string message, int level) 
    { 
     Console.Out.WriteLine(message + " " + level); 
    } 
} 

public abstract class Base 
{ 
    public delegate void logEvent(String message, int level); 

    public event logEvent log; 
} 

public class Sub : Base 
{ 

    public void go() 
    { 
     log("Test", 1); // <-- this wont compile 
    } 
} 
+0

duplicati - http://stackoverflow.com/questions/756237/c -raising-an-inherited-event –

risposta

6

Gli eventi possono essere richiamati solo dalla classe che li dichiara.

Dall'esterno della definizione di una classe (anche in una classe derivata) è possibile registrare e annullare la registrazione solo da event. All'interno della classe, il compilatore consente solo di aumentare l'evento. Questo è un comportamento di progettazione di C# (che in realtà cambia leggermente in C# 4 - Chris Burrows describes the changes on his blog).

Quello che si vuole fare qui è fornire un metodo RaiseLogEvent() nella classe base, che consentirebbe alla classe derivata di richiamare questo evento.

public abstract class Base 
{ 
    public delegate void logEvent(String message, int level); 

    public event logEvent log; 

    protected void RaiseLogEvent(string msg, int level) 
    { 
     // note the idomatic use of the copy/test/invoke pattern... 
     logEvent evt = log; 
     if(evt != null) 
     { 
      evt(msg, level); 
     } 
    } 
} 

Per inciso, si consiglia di utilizzare il tipo di EventHandler<> delegato, piuttosto che creare i propri tipi di evento, quando possibile.

+0

Quindi invece di dichiarare un delegato faccio una sottoclasse di EventArgs che contiene il mio messaggio e loglevel? Perché è meglio? – klundby

+0

@klundy: il modello standard per il gestore di eventi in .NET è quello di fornire un mittente e un oggetto che rappresenta gli argomenti. Ciò consente ai sottoscrittori di inviti di mantenere la coerenza nelle loro firme e riduce la confusione su quali parametri sono previsti. Con la delegazione/contro-varianza del delegato di C# 4 diventa più facile scrivere gestori di eventi generici quando il gestore non si preoccupa degli argomenti o del mittente. Quello che ho fatto in molti casi è creare una classe 'EventArgs ' che eredita da 'EventArgs' e mi consente di passare i dati ai gestori ... ma questa è solo una scelta di stile. – LBushkin

+0

Questo è uno dei più inutili, braindamizzati, frammenti di progettazione linguistica che ho visto da molto tempo. –

2

Perché gli eventi possono essere chiamati solo dalla classe di dichiarazione. Basta creare un metodo nella classe base per chiamarla:

protected virtual RaiseLogEvent(string s, int i) 
{ 
    log(s, i); 
} 

in modo da poter utilizzare nelle classi derivate, e persino ignorare esso.

In un'altra nota, ti consiglio vivamente di seguire le linee guida di progettazione per gli eventi e creare una propria classe EventArgs e utilizzare il delegato EventHandler<T>.

0

Sì, è possibile dichiarare eventi in una classe base in modo che possano essere generati anche da classi derivate.

Creare un metodo di richiamo protetto per l'evento. Chiamando questo metodo di richiamo, le classi derivate possono richiamare l'evento.

Leggere il seguito modo standard per dichiarare gli eventi in una classe base in modo che possano anche essere sollevati dalle classi derivate:

Raise Base Class Events in Derived Classes

Problemi correlati