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

本文关键字:Control 用于 Invoke 参数 方法 转换 | 更新日期: 2023-09-27 18:03:07

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

public void DoSomeStuff()
{
    if (InvokeRequired)
    {
        Invoke((Action)DoSomeStuff);
    }
    else
    {
        // Actually do some stuff.
    }
}

方法组DoSomeStuffAction的显式强制转换引起了我的注意,因此我一直在比以前更深入地研究委托和其他相关主题。

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

在这种情况下,为什么方法组DoSomeStuff需要显式转换为Action ?

如果我删除强制转换,那么我得到两个错误:

错误102参数1:无法从"方法组"转换为的系统。委托'

错误101最佳重载方法匹配"System.Windows.Forms.Control.Invoke(系统。委托,参数对象[])'有一些无效参数

编译器显然对使用Invoke的哪个重载感到困惑,这似乎是一个相当大的暗示,但我仍然不确定为什么它不能弄清楚。我希望编译器能推断出Invoke的第一个重载(它接受一个Delegate参数)是应该使用的重载。

我希望这样做,因为如果代码像这样写的话没有问题:

Action a = DoSomeStuff;
Invoke(a);

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

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

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

你可能会说编译器应该只选择Action/Func类型之一,这已经被要求作为一种语言特性。现在这还不是c#的一部分。(我不知道为什么;我希望语言请求能通过。

System.Windows.Forms.Control.Invoke在。net 1.0中创建。今天,人们会使用以下签名:

void Invoke(Action action);
Task InvokeAsync(Action action);

它会简单地工作。

尝试迁移到await,这不再是一个问题。

使用c# 10和Visual Studio 2022,您不再需要显式强制转换(自然函数类型)。