C# 隐式地将方法组转换为委托(对于Control.Invoke的参数)

C# 隐式地将方法组转换为委托(对于Control.Invoke的参数),c#,delegates,implicit-conversion,C#,Delegates,Implicit Conversion,我正在开发一个Windows窗体应用程序,它包含一些自定义控件,这些控件的方法可以从UI线程以外的线程调用。因此,这些方法看起来有点像这样以防止异常: public void DoSomeStuff() { if (InvokeRequired) { Invoke((Action)DoSomeStuff); } else { // Actually do some stuff. } } 方法组dosomething

我正在开发一个Windows窗体应用程序,它包含一些自定义控件,这些控件的方法可以从UI线程以外的线程调用。因此,这些方法看起来有点像这样以防止异常:

public void DoSomeStuff()
{
    if (InvokeRequired)
    {
        Invoke((Action)DoSomeStuff);
    }
    else
    {
        // Actually do some stuff.
    }
}
方法组
dosomething
动作的显式转换引起了我的注意,因此我比以前更深入地研究了学员和其他相关主题

虽然我在这里看到了一些相关的问题,但我还没有找到我的确切答案,那就是:

在这种情况下,为什么方法组
DoSomeStuff
需要显式强制转换到
操作

如果删除强制转换,则会出现两个错误:

错误102参数1:无法从“方法组”转换为 '系统.代理'

错误101与的最佳重载方法匹配 'System.Windows.Forms.Control.Invoke(System.Delegate,参数 对象[])'有一些无效参数

编译器显然对要使用的
Invoke
重载感到困惑,这一事实似乎是一个很大的暗示,但我仍然不确定为什么它不能确切地理解这一点。我希望编译器推断出应该使用的是
Invoke
的第一个重载,它接受一个
委托
参数

我希望如此,因为如果代码是这样编写的,那么就没有问题了:

Action a = DoSomeStuff;
Invoke(a);

方法组
DoSomeStuff
可以隐式转换为
Action
委托类型,
Action
System.delegate
派生(技术上?),因此
Invoke
可以毫无困难地处理参数
a
。但是,当我试图直接将
dosomething
作为参数传递时,为什么编译器不能完成隐式转换呢?老实说,我不相信我自己的逻辑,但我仍然不确定我遗漏了什么。

问题不是编译器在选择重载时遇到问题。“最佳匹配”重载是您想要的重载,但它具有无效参数。C语言没有定义从方法组(
DoSomeStuff
)到
System.Delegate
的任何隐式转换

您可能会说,编译器应该只选择一种
操作
/
Func
类型,这是作为语言特性请求的。现在这不是C#的一部分。(我不知道为什么,我希望语言申请通过。)

System.Windows.Forms.Control.Invoke是在.NET1.0中创建的。今天,我们将使用以下签名:

void Invoke(Action action);
Task InvokeAsync(Action action);
而且它将简单地工作


尝试将迁移到
wait
,这就不再是一个问题了。

>您可能会说编译器应该只选择一种操作/Func类型,这已被请求作为一种语言功能,这很容易被分解:
void Foo(out string abc)不能使用
操作
函数
表示。如果他们将Action/Func推断实现为一种语言功能,则该功能将被破坏。@GeirGrusom使用此特定签名,转换可能会失败(静态)。这是一种罕见的情况,我认为在这里显示错误是可以的。并非所有方法都可以表示为操作/函数,但其中99%都可以在实践中使用。在有意义的地方,所有委托类型都应该在结构上用隐式转换来处理。我认为这不好。显示错误是因为该功能基本上被破坏了。我不太明白你在这里说的。为什么编译器在某些特殊情况下不能推断方法是动作或Func,这意味着在所有情况下都应该显示错误?按照这种逻辑,DoSomeStuff隐式转换为动作(在原始问题中)也应该是错误的吗?