2009-10-11 6 views
19

Zainstalowałem zdarzenie, aby użyć lambda, które musiało zostać usunięte po wyzwoleniu. Nie mogłem tego zrobić, ustawiając lambdę na zdarzenie + = (brak dostępnej zmiennej do użycia w celu usunięcia zdarzenia), więc ustawiłem zmienną Action<object, EventArgs> i przesunąłem tam lambdę. Główny błąd polegał na tym, że nie można było przekonwertować obiektu Action<object, EventArgs> na obiekt EventHandler. Myślałem, że wyrażenia lambda zostały niejawnie przekształcalne w programy obsługi zdarzeń, dlaczego to nie działa?Akcja <obiekt, EventArgs> nie mogła zostać przeniesiona do EventHandler?

Odpowiedz

33

lambdas są niejawnie zamienny delegować typów z odpowiednim kształcie, ale te same dwa rodzaje kształcie pełnomocnik nie są niejawnie zamienny do siebie. Po prostu ustaw zmienną lokalną na typ EventHandler.

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

(w przypadku pomaga:

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

)

+1

Z tym, że e2 teraz przechodzi przez dwa wywołania funkcji, aby faktycznie zrobić cokolwiek ... eww. –

+3

Nie promuję e2 jako dobrego sposobu pisania kodu, używam go tylko jako przykładu do zademonstrowania, co jest i nie jest legalne w odniesieniu do systemu typu C#. – Brian

+1

@Matthew Scharley - czy zmierzyłeś koszty ogólne? –

0

Można użyć metody anonimowej Zamiast:

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

To cały punkt .... Mam jeden zestaw w górę tylko przechowywane w zmiennej, aby zdarzenie mogło się samo usunąć po uruchomieniu, tylko że nie zadziała. – RCIX

+2

zadeklaruj zmienną jako EventHandler i powinieneś być w porządku ... –

2

Ogólnie delegaci nie mogą być rzucane, ponieważ nie mają dziedziczenia drzewo Definiowanie odlewy są niepoprawne. W tym celu, masz dwie możliwości:

  1. użyć zmiennej typu EventHandler zamiast Action<T1, T2>
  2. użyć deklarację inline.

    // 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

Cały punkt użycia zmiennej był taki, że mogłem usunąć zdarzenie z obsługi zdarzenia, podczas gdy nadal w środku imprezy. Nadal +1. – RCIX

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

To jest naprawdę sprytne. –

0

Stwierdzenie to wydarzenie jako

public event Action<object, EventArgs> e; 

Następnie można bezpośrednio dodawać swoją akcję:

Action<object, EventArgs> a = something; 
e += a; 
Powiązane problemy