2016-12-20 1 views
0

Je veux demander le différent entre EventHandler et EventHandler<T>.EventHandler <T> et EventHandler

Auparavant, j'ai implémenté un EventHandler, avec un EventArgs personnalisé qui peut être passé à la page parente à partir du contrôle utilisateur.

Je pensais que j'ai besoin d'appliquer EventHandler<T>, mais il peut être mis en œuvre en utilisant EventHandler. (en fait il y a erreur bizarre quand j'essaye d'appliquer EventHandler<T>, le programme est travaillé mais l'erreur est montrée dans l'IDE que je n'ai pas pu résoudre [C# Custom EventHandler])

Ainsi, je veux savoir dans quelle situation j'ai besoin appliquer EventHandler <T>?

public event EventHandler AppendProcess; 
public event EventHandler<MyEventArg> AppendProcess; 

--- Mise à jour --- voilà comment j'invoque l'événement dans le contrôle de l'utilisateur (comme je l'ai dit, je peux passer à la page objet parent en faisant cela (même si je ne sais pas si ce est correct de le faire)

if (AppendProcess == null) { } 
else 
    AppendProcess(this, new Common.WinLose_ProgressStage(Common.WinLose_SP_Parameter.upper, displayLevel + 1, 
                  (int)Common.WinLose_Level.lvChild4, thename, refundratio, 
                  selfproportion, -1, -1, loadlevel, isPlayer, betsource, gamecategory, false)); 
+0

avec '' EventHandler vous pouvez passer paramètre de type 'T' aux abonnés. avec 'EventHandler' vous ne pouvez pas passer de paramètres (c'est-à-dire juste' EventArgs.Empty' qui est inutile) –

+1

@ M.kazemAkhgary Vous pouvez (et l'OP) passer dans des classes concrètes dérivées de 'EventArgs', et vous pouvez (et le OP fait) cast le paramètre au type de classe concret à l'intérieur du gestionnaire. Je ne le recommande certainement pas, mais dire "vous ne pouvez pas" après l'OP a déjà montré que vous ne pouvez pas aider. – hvd

Répondre

5

EventHandler<T> est juste un type générique EventHandler, ce qui vous évite de devoir déclarer un nouveau type de délégué pour chaque type de EventArgs que vous souhaitez utiliser.

Tenez compte pour Exemple. Il est déclaré comme un événement de type KeyPressEventHandler. Ce délégué est simplement déclaré:

public delegate void KeyPressEventHandler(object sender, KeyPressEventArgs e) 

Si EventHandler<T> (et génériques) avaient été autour quand cela a été créé, l'événement aurait été déclaré comme lieu EventHandler<KeyPressEventArgs>, l'enregistrement d'une déclaration de délégué. Il y a beaucoup, beaucoup de délégués qui sont juste comme EventHandler, et ne varient que dans le type du deuxième paramètre - EventHandler<T> évite cette redondance.

Non si vous ne avoir votre propre coutume EventArgs sous-classe, il n'y a aucune raison d'utiliser EventHandler<T> ... mais si vous le faites, il est préférable de l'utiliser, de sorte que la méthode manipulation l'événement reçoit votre sous-classe personnalisée EventArgs d'une manière fortement typée. En outre, votre façon d'appeler le gestionnaire d'événements n'est pas sûre pour les threads. Un autre thread peut se désabonner du gestionnaire d'événements final après votre vérification de nullité. Si vous utilisez C# 5, vous devriez l'écrire comme:

var handler = AppendProcess; 
if (handler != null) 
{ 
    handler(this, new Common.WinLose_ProgressStage(...)); 
} 

Si vous utilisez C# 6 ou ultérieur, vous pouvez utiliser l'opérateur conditionnel null:

// If AppendProcess is null, the arguments won't even be evaluated 
AppendProcess?.Invoke(this, new Common.WinLose_ProgressStage(...)); 
+0

J'ai l'impression que cela répond à une question que le PO n'a pas posée, et évite de répondre à la question posée par le PO. L'OP ne pose pas de questions sur 'EventHandler ' vs 'KeyPressEventHandler', l'OP pose des questions sur' EventHandler 'vs' EventHandler'. – hvd

+0

@hvd: Éditera pour clarifier. (Bien que je dirais qu'il répond à la question posée dans la première phrase ...) –

+0

ok, donc EventHandler < T > est comme un paramètre dactylographiés forts de la fonction. et la principale différence entre eventHandler et la fonction normale est que le gestionnaire d'événements doit dans le format (objet, EventArgs), dans ce cas, quand je voulais définir les EventArgs fortement typés afin d'éviter Invoke non valide du contrôle utilisateur, je dois apply EventHandler < T>. Je pense que je comprends mieux sur EventHandler maintenant. Merci – SKLTFZ

4

EventHandler<T> est le générique variante de EventHandler. Habituellement, vous devez remplacer EventArgs et EventHandler pour trouver un type d'événement propre. Vous devez toujours dériver EventArgs si vous souhaitez transmettre des propriétés personnalisées à l'argument e, mais vous n'avez plus besoin de créer un délégué personnalisé pour EventHandler.Vous pouvez maintenant simplement dire:

public event EventHandler<SomeEventArgs> SomeEvent; 

Ce qui est plus pratique que:

public delegate void SomeEventHandler(object sender, SomeEventArgs e); 

public event SomeEventHandler SomeEvent; 

Lorsque votre signature délégué ne change pas, EventHandler<T> est beaucoup plus simple à utiliser.

+1

Et bien sûr EventArgs peuvent être obtenus avec un EventArgs pour se débarrasser de tracas la création de classes personnalisées pour chaque type! –

+1

@ J.R. 'EventArgs ' n'est pas un type standard cependant.Cela peut être une option si vous avez déjà une bibliothèque qui la définit, mais si ce n'est pas le cas, vous devez créer une classe personnalisée de toute façon. – hvd

+0

J'ai trouvé l'information similaire dans mes précédentes recherches! merci pour la clarification – SKLTFZ

2

De votre autre question:

Common.WinLose_ProgressStage wps = (Common.WinLose_ProgressStage)e; 

C'est un casting qui pourrait échouer, selon la façon dont la méthode est invoquée. Rien ne garantit que votre gestionnaire d'événements est uniquement appelé avec Common.WinLose_ProgressStage qui peut être inspecté sans vérifier votre programme complet. Il pourrait être appelé avec un EventArgs aussi: vous avez rendu cela possible en faisant le type de paramètre EventArgs.

EventHandler<T> provoque plus la compilation vérification de type. Si l'autre code tente de transmettre EventArgs.Empty, l'appel échoue simplement à compiler.

Il est fondamentalement la même chose que « pourquoi je ne devrais pas faire tous mes paramètres de type object »? Bien sûr, vous pourriez le faire. Et si vous faites cela, en retournant là où vous en avez besoin, votre code fonctionnera. Mais je sais que je préfère

long Add(long x, long y) { return x + y; } 

sur

object Add(object x, object y) { return (long)x + (long)y; } 

et je pense que dans ce cas, vous aussi. Pourtant, c'est exactement ce que vous faites lorsque vous faites le type de paramètre EventArgs plutôt que Common.WinLose_ProgressStage.

+0

mon problème est que l'application EventHandler (comme vous avez vu dans le post précédent), une erreur se produirait et je ne pouvais pas trouver de solution pour les supprimer, intéressant fonctionnellement le programme fonctionne, juste que le code est souligné en rouge. Je suis d'accord que la fonction dans la page parente n'est pas garantie sans erreur, le jeu de paramètres de la fonction était public void Append_UC_Progress (expéditeur d'objet, Common.WinLose_ProgressStage e), juste je n'ai pas le choix de l'éditer pour corriger cette erreur , et finalement d'autres questions se sont produites. merci – SKLTFZ

+0

@SKLTFZ Oui, je comprends cela, et si j'avais une réponse à votre autre question, j'y répondrais aussi, mais malheureusement je ne le sais pas. – hvd