Reg*_*dit 2 .net c# delegates winforms
Control.BeginInvoke:


在这两种情况下,似乎很清楚编译器具有推断委托类型所需的所有信息.然而,在这两种情况下,类型推断似乎都不起作用:
BeginInvoke(myMethodThatTakesNoParams);
Run Code Online (Sandbox Code Playgroud)
产生编译错误
错误105'System.Windows.Forms.Control.BeginInvoke(System.Delegate)'的最佳重载方法匹配有一些无效的参数
同样如此
BeginInvoke(ShowProcessErrors, new object[] { process });
Run Code Online (Sandbox Code Playgroud)
两个方法调用只有在我将其更改为explitly创建委托并传递它时才会编译.以下两种编译都很好:
BeginInvoke(new MethodInvoker(myMethodThatTakesNoParams));
Run Code Online (Sandbox Code Playgroud)
和
BeginInvoke(new ProcessErrorDelegate(ShowProcessErrors), new object[] { process });
Run Code Online (Sandbox Code Playgroud)
似乎没有任何明显的理由为什么类型推断在这里不起作用.有BeginInvoke没有明确创建委托的方法来调用?
问题在于它myMethodThatTakesNoParams不是真正的委托,而是编译器所谓的"方法组".方法组不是CLR中的真实类型.必须将其转换为要使用的委托类型.当您使用这样的方法组时:
Action a = myMethodThatTakesNoParams;
Run Code Online (Sandbox Code Playgroud)
编译器识别出您要将方法组转换为委托并为您插入转换.它产生的IL有效地说:
Action a = new Action(myMethodThatTakesNoParams);
Run Code Online (Sandbox Code Playgroud)
当你说:
Delegate d = myMethodThatTakesNoParams
Run Code Online (Sandbox Code Playgroud)
编译器实际上不知道该怎么做.从理论上讲,它可以为您选择任何兼容的委托类型,但C#通常不会将您未使用的类型插入表达式中.由于它不知道您希望方法组转换为什么委托,因此编译器会产生错误.
我在我的示例中使用了变量赋值,但是相同的逻辑适用于方法的参数.
解决方法是编写自己的扩展方法,其中包含特定的委托类型:
static class ControlExtensions
{
public static IAsyncResult BeginInvoke(this Control c, Action a)
{
return c.BeginInvoke(a);
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
134 次 |
| 最近记录: |