将方法组隐式转换为Delegate(用于Control.Invoke的参数) [英] Implicitly convert method group to Delegate (for argument of Control.Invoke)
问题描述
我正在使用Windows Forms应用程序,它包含一些自定义控件,这些控件的方法可以从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.
}
}
方法组<$ c $的显式转换c> 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,params
object [])'有一些无效的参数
Error 101 The best overloaded method match for 'System.Windows.Forms.Control.Invoke(System.Delegate, params object[])' has some invalid arguments
编译器显然混淆了一个事实关于使用 Invoke
的重载似乎是一个很大的提示,但是我仍然不确定为什么它无法弄清楚。我希望编译器推断出 Invoke
的第一个重载就是一个,它只需要一个 Delegate
参数。
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 $之一c>类型,这已被要求作为语言功能。现在,这不是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.
这篇关于将方法组隐式转换为Delegate(用于Control.Invoke的参数)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!