问题描述
我正在开发一个 Windows 窗体应用程序,它包含自定义控件以及可以从 UI 线程以外的线程调用的方法.所以这些方法因此看起来有点像这样来防止异常:
I'm working on a Windows Forms application, and it contains custom controls with methods that can potentially be called from threads other than the UI thread. So these methods therefore look a bit like this to prevent exceptions:
public void DoSomeStuff()
{
if (InvokeRequired)
{
Invoke((Action)DoSomeStuff);
}
else
{
// Actually do some stuff.
}
}
方法组 DoSomeStuff
到 Action
的显式转换引起了我的注意,因此我对委托和其他相关主题的研究比我以前更深入之前.
The explicit cast of the method group DoSomeStuff
to an Action
caught my attention, and so I've been looking into delegates and other related subjects more deeply than I have before.
虽然我在这里看到了一些相关的问题,但我一直无法找到我的确切答案,即:
Although I've seen some related questions here, I haven't been able to find exactly the answer to mine, which is:
在这种情况下,为什么方法组 DoSomeStuff
需要显式转换为 Action
?
Why does the method group DoSomeStuff
require explicit casting to an Action
in this case?
如果我删除演员表,则会收到两个错误:
If I remove the cast, then I get two errors:
错误 102 参数 1:无法从方法组"转换为'System.Delegate'
Error 102 Argument 1: cannot convert from 'method group' to 'System.Delegate'
错误 101 的最佳重载方法匹配'System.Windows.Forms.Control.Invoke(System.Delegate,参数object[])' 有一些无效参数
Error 101 The best overloaded method match for 'System.Windows.Forms.Control.Invoke(System.Delegate, params object[])' has some invalid arguments
编译器显然对使用哪个 Invoke
重载感到困惑这一事实似乎是一个很大的提示,但我仍然不确定为什么它无法弄清楚这一点.我希望编译器能够推断出应该使用单个 Delegate
参数的 Invoke
的第一个重载.
The fact that the compiler is apparently confused about which overload of Invoke
to use seems like a pretty big hint, but I'm still not sure about why exactly it can't figure that out. I would expect the compiler to deduce that the first overload of Invoke
, which takes a single Delegate
argument, is the one that should be used.
我希望因为这样写代码没有问题:
I would expect that because there is no problem if the code is written like this:
Action a = DoSomeStuff;
Invoke(a);
方法组 DoSomeStuff
可以隐式转换为 Action
委托类型,并且 Action
派生自(技术上?)System.Delegate
,所以 Invoke
可以毫无问题地处理参数 a
.但是,当我尝试直接将 DoSomeStuff
作为参数传递时,为什么编译器不能完成隐式转换呢?老实说,我不相信我自己的逻辑,但我仍然不确定我错过了什么.
The method group DoSomeStuff
can be implicitly converted to the Action
delegate type, and Action
derives (technically?) from System.Delegate
, so Invoke
can handle the argument a
without any trouble. But then why can't the implicit conversion be done by the compiler when I try to pass DoSomeStuff
as the argument directly? To be honest I'm not convinced by my own logic here, but I still am not sure what I'm missing.
推荐答案
问题不在于编译器无法选择重载.最佳匹配"重载是您想要的重载,但它具有无效参数.C# 语言没有定义任何从方法组 (DoSomeStuff
) 到 System.Delegate
的隐式转换.
The problem is not that the compiler has trouble picking an overload. The "best match" overload is the one you want but it has invalid arguments. The C# language does not define any implicit conversion from method group (DoSomeStuff
) to System.Delegate
.
您可能会说编译器应该只选择一种 Action
/Func
类型,而这已作为语言特性被请求.现在这不是 C# 的一部分.(我不知道为什么;我希望语言请求能够通过.)
You might say that the compiler should just pick one of the Action
/Func
types and this has been requested as a language feature. Right now this is not part of C#. (I don't know why; I hope the language request goes through.)
System.Windows.Forms.Control.Invoke
是在 .NET 1.0 中创建的.今天,人们会使用以下签名:
System.Windows.Forms.Control.Invoke
was created in .NET 1.0. Today, one would use the following signatures:
void Invoke(Action action);
Task InvokeAsync(Action action);
而且它会简单地工作.
尝试迁移到 await
,这不再是一个问题.
Try to make the migration to await
and this stops being a concern.
这篇关于将方法组隐式转换为委托(用于 Control.Invoke 的参数)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!