2009-10-11 1 views
19

Я подключил событие, чтобы использовать лямбду, которая должна была удалиться после запуска. Я не мог этого сделать, вставив лямбда в событие + = (без переменной доступа, используемой для удаления события), поэтому я установил переменную Action<object, EventArgs> и переместил там лямбда. Основная ошибка заключалась в том, что он не смог преобразовать Action<object, EventArgs> в EventHandler. Я думал, что лямбда-выражения неявно конвертируются в обработчики событий, почему это не работает?Действие <объект, EventArgs> не может быть передано в EventHandler?

ответ

33

Лямбда неявно конвертируемая делегировать типы с правильной формой, но два одинаковых-формой типа делегата не неявно преобразован друг к другу. Просто сделайте, чтобы локальная переменная имела тип EventHandler.

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

(в случае, если это помогает:

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

)

+1

За исключением того, что e2 теперь проходит через два вызова функций, чтобы на самом деле что-либо сделать ... eww. –

+3

Я не продвигаю e2 как хороший способ писать код, я просто использую его в качестве примера, чтобы продемонстрировать, что есть и не является законным в отношении системы типа C#. – Brian

+1

@Matthew Scharley - вы измерили накладные расходы? –

0

Вы можете использовать анонимный метод вместо:

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

Вот весь смысл .... У меня есть один набор только сохраняется в переменной, чтобы я мог удалить событие при запуске, только он не будет работать. – RCIX

+2

объявить переменную как EventHandler, и вы должны быть в порядке ... –

2

В целом, делегаты не могут быть отлиты, потому что они не имеют никакого наследования дерева определения того, какие броски действительны. С этой целью, у вас есть два варианта:

  1. использовать переменную типа EventHandler вместо Action<T1, T2>
  2. Используйте инлайн декларацию.

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

Весь смысл использования переменной состоял в том, что я мог удалить событие из обработчика события, все еще внутри события. Тем не менее, +1. – RCIX

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

Это действительно умно. –

0

Объявите ваше событие как

public event Action<object, EventArgs> e; 

Тогда вы можете напрямую добавить свое действие:

Action<object, EventArgs> a = something; 
e += a; 
Смежные вопросы