Control.BeginInvoke
:
在这两种情况下,显然编译器拥有推断委托类型所需的所有信息。但是在两种情况下,类型推断似乎都不起作用:
BeginInvoke(myMethodThatTakesNoParams);
产生编译器错误
错误105最佳重载方法匹配为'System.Windows.Forms.Control.BeginInvoke(System.Delegate)'有一些无效的参数
一样
BeginInvoke(ShowProcessErrors, new object[] { process });
这两种方法仅在我更改它们以直接创建一个委托并将其传递时才进行编译。以下两个都可以正常编译:
BeginInvoke(new MethodInvoker(myMethodThatTakesNoParams));
和
BeginInvoke(new ProcessErrorDelegate(ShowProcessErrors), new object[] { process });
似乎没有任何明显的原因使类型推断在这里不起作用。是否可以在BeginInvoke
不显式创建委托的情况下进行呼叫?
问题是,myMethodThatTakesNoParams
它实际上不是委托,而是编译器的所谓“方法组”。方法组在CLR中不是真实类型。必须将其转换为要使用的委托类型。当使用这样的方法组时:
Action a = myMethodThatTakesNoParams;
编译器识别出您要将方法组转换为委托,并为您插入转换。它产生的IL有效地表示:
Action a = new Action(myMethodThatTakesNoParams);
当你说:
Delegate d = myMethodThatTakesNoParams
编译器并不真正知道该怎么做。从理论上讲,它可以为您选择任何兼容的委托类型,但是C#通常不会将您未使用的类型插入表达式中。由于它不知道您要将方法组转换为什么委托,因此编译器会产生错误。
我在示例中使用了变量赋值,但是相同的逻辑适用于方法的参数。
解决方法是编写自己的扩展方法,其中具有特定的委托类型:
static class ControlExtensions
{
public static IAsyncResult BeginInvoke(this Control c, Action a)
{
return c.BeginInvoke(a);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句