匿名方法和委托

我试图理解为什么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); }); 

Delegate类是委托类型的基类。 但是,只有系统和编译器可以从Delegate类或MulticastDelegate类显式派生。 也不允许从委托类型派生新类型。 Delegate类不被视为委托类型 ; 它是一个用于派生委托类型的类。 来源 – 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!"); }); } 

更多关于这个页面的Ian Griffith 。 (参见Notes标题后面的段落)

你需要告诉编译器要创建什么类型的委托,因为Invoke (etc)只需要使用Delegate (而不是更具体的东西)。

要应用于最大的受众, MethodInvoker是一个方便的委托类型

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

但是…… BackgroundWorker.ProgressChanged会自动触发UI线程 – 所以你甚至不需要这样做。

大多数情况下,在这些情况下,您要处理无参数委托或谓词。 最简单的排序方法是将匿名方法分别直接转换为ActionPredicate ; 您只需要为这样的简单事物创建自定义委托类型。

所以你会有类似的东西

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

要么

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

HTH