2010-10-16 17 views
67

Ho bisogno di avere alcuni delegati nella mia classe.Come aggiungere un delegato a un'interfaccia C#

Mi piacerebbe utilizzare l'interfaccia per "ricordarmi" di impostare questi delegati.

Come?

mio aspetto classe come questa:

public class ClsPictures : myInterface 
{ 
    // Implementing the IProcess interface 
    public event UpdateStatusEventHandler UpdateStatusText; 
    public delegate void UpdateStatusEventHandler(string Status); 

    public event StartedEventHandler Started; 
    public delegate void StartedEventHandler(); 
} 

ho bisogno di un'interfaccia per forzare i delegati:

public interface myInterface 
{ 
    // ????? 
} 

risposta

115

Quelli sono dichiarando delegato tipi. Non appartengono a un'interfaccia. Gli eventi utilizzando questi tipi delegato sono benissimo essere nell'interfaccia però:

public delegate void UpdateStatusEventHandler(string status); 
public delegate void StartedEventHandler(); 

public interface IMyInterface 
{  
    event UpdateStatusEventHandler StatusUpdated;  
    event StartedEventHandler Started; 
} 

L'attuazione non (e non dovrebbe) ridichiarare il tipo delegato, più di quanto non sarebbe ridichiarare qualsiasi altro tipo usato in un'interfaccia.

+0

Questo semplicemente non funziona per me. Sono sicuro di aver fatto tutto in questo modo, eppure il mio gestore all'interno della mia interfaccia non viene riconosciuto. La mia classe che implementa l'interfaccia si lamenta che la classe non corrisponde al tipo di interfaccia di ritorno di System.EventHandler. – Chucky

+1

@Chucky: Sembra che dovresti fare una nuova domanda con un esempio breve ma completo che dimostra il problema. La risposta che ho dato davvero * funziona *. –

+4

Non mi sono reso conto che i delegati hanno lo stesso livello di accessibilità delle classi. Ho sempre pensato che dovessero essere incapsulati all'interno di una classe. – Purusartha

6

La risposta di Jon Skeet è giusta, voglio solo aggiungere una nota.

Le interfacce non sono lì per "ricordare" cosa fare o cosa includere nelle classi. Le interfacce sono mezzi di astrazione, usati nella programmazione orientata agli oggetti e nei metodi di progettazione. Forse non hai bisogno di una dichiarazione dell'interfaccia, a meno che tu non voglia vedere alcune istanze di classe concrete come l'interfaccia in altre parti del tuo programma (Abstraction).

Se si desidera applicare alcuni standard di codifica nel progetto, è possibile provare a utilizzare gli strumenti di analisi del codice (come in Visual Studio). Consentono estensioni che è possibile incorporare per aggiungere le proprie regole di analisi del codice.

Utilizzando l'analisi del codice, se si "dimentica" di aggiungere i delegati (anche se non vedo il punto di dimenticarlo, come se il delegato non è utilizzato, non è necessario) si otterrà un avviso/errore .

+1

Forse hai ragione, ma ci sono delle volte in cui fai delle ipotesi che anche con una buona documentazione è difficile da ricordare dopo un po '. Cerco di riutilizzare il mio codice ma a volte non riesco a ricordare quale sia il nucleo e cosa no (quando si tratta di delegati - è difficile per me vedere il quadro generale ...) – Asaf

23

Dal .NET 3.5 è possibile utilizzare anche i delegati System.Action, il che porterebbe alla seguente interfaccia:

public class ClsPictures : myInterface 
{  
    // Implementing the IProcess interface 
    public event Action<String> UpdateStatusText; 

    public event Action Started; 
} 
+0

+1. Trovo che Action/Func sia molto più elegante (e leggibile) dei tipi di delegati tradizionali e che sia possibile definirli nell'interfaccia. – chrnola

0

L'interfaccia ereditata all'interno della vostra classe derivata vi ricorderà di definire e collegare la roba ci hai dichiarato.

Ma potresti anche volerlo usare esplicitamente e dovrai comunque associarlo a un oggetto.

Ad esempio, utilizzando un'inversione del modello di controllo:

class Form1 : Form, IForm { 
    public Form1() { 
    Controls.Add(new Foo(this)); 
    } 

    // Required to be defined here. 
    void IForm.Button_OnClick(object sender, EventArgs e) { 
    ... 
    // Cast qualifier expression to 'IForm' assuming you added a property for StatusBar. 
    //((IForm) this).StatusBar.Text = $"Button clicked: ({e.RowIndex}, {e.SubItem}, {e.Model})"; 
    } 
} 

si può provare qualcosa di simile.

interface IForm { 
    void Button_OnClick(object sender, EventArgs e); 
} 


class Foo : UserControl { 
    private Button btn = new Button(); 

    public Foo(IForm ctx) { 
    btn.Name = "MyButton"; 
    btn.ButtonClick += ctx.Button_OnClick; 
    Controls.Add(btn); 
    } 
} 
1

Uno dei commenti ha fatto riferimento al tipo di ritorno del gestore eventi. Sei più interessato al tipo di gestore o ai dati che tornano dall'evento? Se è il secondo, allora questo può aiutare. In caso contrario, questa soluzione non sarà sufficiente, ma potrebbe aiutarti ad avvicinarti a ciò che stai cercando.

Tutto ciò che dovete fare è dichiarare i gestori di eventi come gestori di eventi generici sia nell'interfaccia che nella vostra implementazione e potete personalizzare i risultati di ritorno.

La classe conrete sarebbe simile a questa:

public class ClsPictures : myInterface 
{ 
    // Implementing the IProcess interface 
    public event EventHandler<UpdateStatusEventArgs> UpdateStatusText; 
    //no need for this anymore: public delegate void UpdateStatusEventHandler(string Status); 

    public event EventHandler<StartedEventArgs> Started; 
    //no need for this anymore: public delegate void StartedEventHandler(); 
} 

L'interfaccia sarà simile a questa:

public interface myInterface 
{ 
    event EventHandler<StartedEventArgs> Started; 
    event EventHandler<UpdateStatusEventArgs> UpdateStatusText; 
} 

Ora che gli argomenti degli eventi stanno tornando i tipi di, è possibile li agganciare in qualsiasi gestore tu definisci.

Per riferimento: https://msdn.microsoft.com/en-us/library/edzehd2t(v=vs.110).aspx

3

esporre Proprio il delegato come una proprietà

public delegate void UpdateStatusEventHandler(string status); 
public delegate void StartedEventHandler(); 

public interface IMyInterface 
{  
    UpdateStatusEventHandler StatusUpdated {get; set;}  
    StartedEventHandler Started {get; set;} 
}