Анонимные методы и делегаты - PullRequest
14 голосов
/ 09 июня 2009

Я пытаюсь понять, почему метод BeginInvoke не принимает анонимный метод.

void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if (InvokeRequired)
    {
        //Won't compile
        BeginInvoke(delegate(object sender, ProgressChangedEventArgs e) 
        { bgWorker_ProgressChanged(sender, e); });
    }

    progressBar1.Increment(e.ProgressPercentage);
}

В нем говорится, что «невозможно преобразовать из« анонимного метода »в« System.Delegate », в то время как когда я приводил анонимный метод к делегату, он работает?

BeginInvoke((progressDelegate)delegate { bgWorker_ProgressChanged(sender, e); });

Ответы [ 3 ]

16 голосов
/ 09 июня 2009

Вы должны указать компилятору, какой тип делегата создать, поскольку Invoke (и т. Д.) Просто принимают Delegate (а не что-то более конкретное).

Чтобы обратиться к самой большой аудитории, MethodInvoker - это удобный тип делегата

BeginInvoke((MethodInvoker) delegate(...) {...});

Однако ... BackgroundWorker.ProgressChanged автоматически запускает поток пользовательского интерфейса - так что вам это даже не нужно.

7 голосов
/ 09 июня 2009

Класс Delegate является базовым классом для типов делегатов. Однако только система и компиляторы могут быть явно получены из класса Delegate или из класса MulticastDelegate. Также недопустимо выводить новый тип из типа делегата. Класс делегата не считается типом делегата ; это класс, используемый для получения типов делегатов. Источник - MSDN

Отсюда необходимость явного приведения к типу производного от делегата. Эта конкретная ошибка компилятора может возникнуть при передаче анонимного метода для параметра типа System.Delegate - к счастью, это редкий сценарий. Это слишком большая гибкость.

delegate void MyDelegate();

  static void DoSomething_Flexible(Delegate d)
  {   d.DynamicInvoke();      }
  static void DoSomething_Usable(MyDelegate d)
  {   d();      }
  static void Main(string[] args)
  {
     // requires explicit cast else compile error Error "Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type    
     DoSomething_Flexible((MyDelegate) delegate { Console.WriteLine("Flexible is here!"); });  

     // Parameter Type is a .NET Delegate, no explicit cast needed here. 
     DoSomething_Usable(delegate { Console.WriteLine("Usable is here!"); });
  }

Подробнее об этом на этой странице Яна Гриффита . (См. Пункты после заголовка Примечания)

5 голосов
/ 08 декабря 2009

В этих случаях большую часть времени вы имеете дело с делегатом без параметров или предикатом. Самый простой способ сортировки это путем непосредственного приведения вашего анонимного метода к Action или Predicate соответственно; вам просто не нужно создавать пользовательский тип делегата для простых вещей, подобных этому.

Так что у вас будет что-то вроде

BeginInvoke((Action)delegate(){YourCode.DoSomething();});

или

BeginInvoke((Predicate)delegate(object yourParameter){return YourCode.IsTheParameterSomething(yourParameter)});

НТН

...