委托/lambda 类型和强制如何工作?
我注意到在处理 C# 中的 lambda 函数和匿名委托时,一些有效和无效的示例。这是怎么回事?
class Test : Control {
void testInvoke() {
// The best overloaded method match for 'Invoke' has some invalid arguments
Invoke(doSomething);
// Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type
Invoke(delegate { doSomething(); });
// OK
Invoke((Action)doSomething);
// OK
Invoke((Action)delegate { doSomething(); });
// Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type
Invoke(() => doSomething());
// OK
Invoke((Action)(() => doSomething()));
}
void testQueueUserWorkItem() {
// The best overloaded method match for 'QueueUserWorkItem' has some invalid arguments
ThreadPool.QueueUserWorkItem(doSomething);
// OK
ThreadPool.QueueUserWorkItem(delegate { doSomething(); });
// The best overloaded method match for 'QueueUserWorkItem' has some invalid arguments
ThreadPool.QueueUserWorkItem((Action)doSomething);
// No overload for 'doSomething' matches delegate 'WaitCallback'
ThreadPool.QueueUserWorkItem((WaitCallback)doSomething);
// OK
ThreadPool.QueueUserWorkItem((WaitCallback)delegate { doSomething(); });
// Delegate 'WaitCallback' does not take '0' arguments
ThreadPool.QueueUserWorkItem(() => doSomething());
// OK
ThreadPool.QueueUserWorkItem(state => doSomething());
}
void doSomething() {
// ...
}
}
嗯,这样的例子有很多。我想我的问题如下:
为什么
Invoke
总是拒绝 lambda 函数或匿名委托,而ThreadPool.QueueUserWorkItem
却做得很好?“无法将匿名方法转换为“System.Delegate”类型,因为它不是委托类型”到底是什么意思?
为什么 ThreadPool.QueueUserWorkItem 接受不带参数的匿名委托,而不接受不带参数的 lambda 表达式?
I've noticed some examples of things that work and don't work when dealing with lambda functions and anonymous delegates in C#. What's going on here?
class Test : Control {
void testInvoke() {
// The best overloaded method match for 'Invoke' has some invalid arguments
Invoke(doSomething);
// Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type
Invoke(delegate { doSomething(); });
// OK
Invoke((Action)doSomething);
// OK
Invoke((Action)delegate { doSomething(); });
// Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type
Invoke(() => doSomething());
// OK
Invoke((Action)(() => doSomething()));
}
void testQueueUserWorkItem() {
// The best overloaded method match for 'QueueUserWorkItem' has some invalid arguments
ThreadPool.QueueUserWorkItem(doSomething);
// OK
ThreadPool.QueueUserWorkItem(delegate { doSomething(); });
// The best overloaded method match for 'QueueUserWorkItem' has some invalid arguments
ThreadPool.QueueUserWorkItem((Action)doSomething);
// No overload for 'doSomething' matches delegate 'WaitCallback'
ThreadPool.QueueUserWorkItem((WaitCallback)doSomething);
// OK
ThreadPool.QueueUserWorkItem((WaitCallback)delegate { doSomething(); });
// Delegate 'WaitCallback' does not take '0' arguments
ThreadPool.QueueUserWorkItem(() => doSomething());
// OK
ThreadPool.QueueUserWorkItem(state => doSomething());
}
void doSomething() {
// ...
}
}
Well that's a lot of examples. I guess my questions are the following:
Why does
Invoke
always refuse a lambda function or an anonymous delegate, yetThreadPool.QueueUserWorkItem
does just fine?What the heck does "Cannot convert anonymous method to type 'System.Delegate' because it is not a delegate type" mean anyway?
Why does
ThreadPool.QueueUserWorkItem
accept an anonymous delegate with no parameters, but not a lambda expression with no parameters?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
ThreadPool.QueueUserWorkItem
在其签名中有一个特定委托; Invoke 只有Delegate
。 Lambda 表达式和匿名方法只能转换为特定委托类型。这只是一个糟糕的错误消息。这意味着,“我不确切知道您要尝试转换为哪种委托类型。”
您使用的匿名方法根本没有参数列表,它可以转换为任何不使用 out/ref 参数的委托类型。如果您尝试
delegate() { ... }
(即明确为空的参数列表),那么它将不起作用。匿名方法的“我不关心参数”功能是它们唯一具有的功能,而 lambda 表达式则没有。在简单的作业环境中演示所有这些是最简单的,IMO:
ThreadPool.QueueUserWorkItem
has a specific delegate in its signature; Invoke just hasDelegate
. Lambda expressions and anonymous methods can only be converted to a specific delegate type.It's just a bad error message. It means, "I don't know exactly which delegate type you're trying to convert to."
You're using an anonymous method without a parameter list at all which can be converted to any delegate type which doesn't use out/ref parameters. If you tried
delegate() { ... }
(i.e. an explicitly empty parameter list) then it wouldn't work. This "I don't care about parameters" ability of anonymous methods is the only feature they have which lambda expressions don't.It's easiest to demonstrate all of this in the context of simple assignments, IMO: