匿名方法和代理

Mez*_*Mez 14 .net c# delegates anonymous-methods .net-2.0

我试图理解为什么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);
}
Run Code Online (Sandbox Code Playgroud)

它告诉我'无法从'匿名方法'转换为'System.Delegate',而当我将匿名方法转换为委托时,它确实有效吗?

BeginInvoke((progressDelegate)delegate { bgWorker_ProgressChanged(sender, e); });
Run Code Online (Sandbox Code Playgroud)

Mar*_*ell 16

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

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

BeginInvoke((MethodInvoker) delegate(...) {...});
Run Code Online (Sandbox Code Playgroud)

但是... BackgroundWorker.ProgressChanged自动触发UI线程 - 所以你甚至不需要这个.


Gis*_*shu 7

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!"); });
  }
Run Code Online (Sandbox Code Playgroud)

Ian Griffith本页的更多内容.(参见Notes标题后面的段落)


Eig*_*ite 5

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

所以你会有类似的东西

BeginInvoke((Action)delegate(){YourCode.DoSomething();});
Run Code Online (Sandbox Code Playgroud)

要么

BeginInvoke((Predicate)delegate(object yourParameter){return YourCode.IsTheParameterSomething(yourParameter)});
Run Code Online (Sandbox Code Playgroud)

HTH