2009-10-11 5 views
19

J'étais en train de câbler un événement pour utiliser un lambda qui devait s'enlever après le déclenchement. Je ne pouvais pas le faire en insérant le lambda à l'événement + = (aucune variable accessible à utiliser pour supprimer l'événement) donc j'ai mis en place une variable Action<object, EventArgs> et y ai déplacé le lambda. L'erreur principale était qu'il ne pouvait pas convertir un Action<object, EventArgs> en EventHandler. Je pensais que les expressions lambda étaient implicitement convertibles en gestionnaires d'événements, pourquoi cela ne fonctionne-t-il pas?Action <objet, EventArgs> n'a pas pu être converti en EventHandler?

Répondre

33

lambdas sont implicitement convertibles à déléguer types avec la bonne forme, mais deux types de déléguer, en forme ne sont pas implicitement convertibles les uns aux autres. Faites simplement en sorte que la variable locale ait le type EventHandler à la place.

EventHandler h = (o, ea) => { ... }; 
e += h; 
... 
e -= h; 

(dans le cas où il aide:

Action<object, EventArgs> a = (o, ea) => { }; 
EventHandler e = a; // not allowed 
EventHandler e2 = (o,ea) => a(o,ea); // ok 

)

+1

Sauf que e2 passe maintenant par deux appels de fonction pour réellement faire n'importe quoi ... eww. –

+3

Je ne suis pas en train de promouvoir e2 comme un bon moyen d'écrire du code, je l'utilise juste comme un exemple pour montrer ce qui est légal ou pas en ce qui concerne le système de type C#. – Brian

+1

@Matthew Scharley - avez-vous mesuré les frais généraux? –

0

Vous pouvez utiliser une méthode anonyme à la place:

Event += (sender, e) => 
{ 
    // Multiple lines 
    // of code here 
}; 
+1

Ce point est tout .... J'ai un ensemble up seulement stocké dans une variable que je peux avoir l'événement se retirer lorsqu'il est viré, seulement cela ne fonctionnera pas. – RCIX

+2

déclarez la variable comme EventHandler et vous devriez être OK ... –

2

En général, les délégués ne peuvent pas être jeté parce qu'il n'a pas de définition arbre d'héritage qui moulages sont valides. À cette fin, vous avez deux choix:

  1. Utilisez une variable de type EventHandler au lieu du Action<T1, T2>
  2. Utilisez une déclaration en ligne.

    // option 1: local variable 
    EventHandler eh = (o, ea) => { /* [snip] */ }; 
    obj.event += eh; 
    obj.event -= eh; 
    
    // option 2: inline declaration 
    obj.event += (o, ea) => { /* [snip] */ }; 
    
+0

Le point entier de l'utilisation d'une variable était de pouvoir supprimer l'événement du gestionnaire d'événements toujours à l'intérieur de l'événement. Encore, +1. – RCIX

36
Action<Object, EventArgs> a = (o, ea) => { }; 
EventHandler e = a.Invoke; 
+1

C'est vraiment intelligent. –

0

Déclarez votre événement

public event Action<object, EventArgs> e; 

Ensuite, vous pouvez ajouter directement votre action:

Action<object, EventArgs> a = something; 
e += a; 
Questions connexes