将方法组隐式转换为委托(对于 Control.Invoke 的参数)
Implicitly convert method group to Delegate (for argument of Control.Invoke)
我正在开发 Windows Forms 应用程序,它包含自定义控件,其方法可能会从 UI 线程以外的线程调用。所以这些方法因此看起来有点像这样以防止异常:
public void DoSomeStuff()
{
if (InvokeRequired)
{
Invoke((Action)DoSomeStuff);
}
else
{
// Actually do some stuff.
}
}
方法组 DoSomeStuff
到 Action
的显式转换引起了我的注意,因此我比以前更深入地研究了委托和其他相关主题。
虽然我在这里看到了一些相关问题,但我一直无法找到我的确切答案,即:
在这种情况下,为什么方法组 DoSomeStuff
需要显式转换为 Action
?
如果删除强制转换,则会出现两个错误:
Error 102 Argument 1: cannot convert from 'method group' to
'System.Delegate'
Error 101 The best overloaded method match for
'System.Windows.Forms.Control.Invoke(System.Delegate, params
object[])' has some invalid arguments
编译器显然对使用 Invoke
的哪个重载感到困惑这一事实似乎是一个很大的提示,但我仍然不确定为什么它无法弄清楚这一点。我希望编译器推断出 Invoke
的第一个重载,它采用单个 Delegate
参数,是应该使用的
我希望是这样,因为如果代码这样写就没有问题:
Action a = DoSomeStuff;
Invoke(a);
方法组 DoSomeStuff
可以隐式转换为 Action
委托类型,并且 Action
从 System.Delegate
派生(技术上?),所以 Invoke
可以毫无问题地处理参数 a
。但是为什么当我试图直接将 DoSomeStuff
作为参数传递时,编译器不能完成隐式转换呢?老实说,我不相信我自己的逻辑,但我仍然不确定我错过了什么。
问题不在于编译器无法选择重载。 "best match" 重载是您想要的重载,但它的参数无效。 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,您不再需要显式转换(自然函数类型)。
我正在开发 Windows Forms 应用程序,它包含自定义控件,其方法可能会从 UI 线程以外的线程调用。所以这些方法因此看起来有点像这样以防止异常:
public void DoSomeStuff()
{
if (InvokeRequired)
{
Invoke((Action)DoSomeStuff);
}
else
{
// Actually do some stuff.
}
}
方法组 DoSomeStuff
到 Action
的显式转换引起了我的注意,因此我比以前更深入地研究了委托和其他相关主题。
虽然我在这里看到了一些相关问题,但我一直无法找到我的确切答案,即:
在这种情况下,为什么方法组 DoSomeStuff
需要显式转换为 Action
?
如果删除强制转换,则会出现两个错误:
Error 102 Argument 1: cannot convert from 'method group' to 'System.Delegate'
Error 101 The best overloaded method match for 'System.Windows.Forms.Control.Invoke(System.Delegate, params object[])' has some invalid arguments
编译器显然对使用 Invoke
的哪个重载感到困惑这一事实似乎是一个很大的提示,但我仍然不确定为什么它无法弄清楚这一点。我希望编译器推断出 Invoke
的第一个重载,它采用单个 Delegate
参数,是应该使用的
我希望是这样,因为如果代码这样写就没有问题:
Action a = DoSomeStuff;
Invoke(a);
方法组 DoSomeStuff
可以隐式转换为 Action
委托类型,并且 Action
从 System.Delegate
派生(技术上?),所以 Invoke
可以毫无问题地处理参数 a
。但是为什么当我试图直接将 DoSomeStuff
作为参数传递时,编译器不能完成隐式转换呢?老实说,我不相信我自己的逻辑,但我仍然不确定我错过了什么。
问题不在于编译器无法选择重载。 "best match" 重载是您想要的重载,但它的参数无效。 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,您不再需要显式转换(自然函数类型)。