匿名方法和委托

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

1
也可以看一下这个问题:https://dev59.com/cnVC5IYBdhLWcg3wjx_u - tanascius
3个回答

16
你需要告诉编译器创建哪种委托类型,因为Invoke(等等)只需要取Delegate(而非更具体的内容)。
为了适用于最广泛的受众,MethodInvoker是一个方便的委托类型。
BeginInvoke((MethodInvoker) delegate(...) {...});

然而... BackgroundWorker.ProgressChanged 会自动在UI线程上触发,所以你甚至不需要这样做。


7

Delegate类是委托类型的基类。但是,只有系统和编译器可以明确从Delegate类或MulticastDelegate类派生。也不允许从委托类型派生新类型。 Delegate类不被视为委托类型;它是用来派生委托类型的类。 来源--MSDN

因此需要将其显式转换为派生自Delegate类型。当您将匿名方法作为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标题后的段落)


不错的回答,但我不确定我会将SomeControl.BeginInvoke(Delegate method, param object[] args)描述为“罕见”。 - Peter Wone
@PeterWone - :). 我建议使用BackgroundWorker实例来处理UI线程亲和性。对于已经以这种方式编写的现有第三方方法,您无法做任何事情 - 您需要标记为小型(Action)转换。 - Gishu

5

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

因此,您会得到类似以下内容:

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

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

HTH


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接