繁体   English   中英

编译器如何从LAMBDA表达式推断出委托类型?

[英]How does compiler infer the delegate type from LAMBDA expression?

示例代码

int id = 123;

ThreadPool.QueueUserWorkItem(state => ThreadEntryPoint((int)state), id);

public void ThreadEntryPoint(int uniqueId)
{
   Console.WriteLine("uniqueId=" + uniqueId);
}

从提供的LAMBDA表达式中,编译器如何知道它需要创建QueueUserWorkItem(WaitCallback, Object)的实例?

更具体地说:我理解它推断了委托类型。 我不明白是什么决策树(从高层次)选择正确的委托类型进行实例化?

参考

编译器如何从LAMBDA表达式推断出委托类型?

从根本上说,它没有。

编译器从名为QueueUserWorkItem的方法组中的可用重载推断出委托类型。 只有两个重载,只有一个有两个参数,两个重载都使用委托类型WaitCallback

因此,委托类型必须WaitCallback 通过这个确定,编译器然后可以将lambda表达式编译为匿名方法,并实例化为QueueUserWorkItem()方法的参数,调用必要的委托对象来调用该匿名方法。

在更复杂的情况下,编译器必须执行一些分析以确定重载的“最佳”匹配,并且该分析可能涉及lambda表达式,以至于它可以消除基于lambda表达式的过载可能性。

但是编译器在任何时候都不会从lambda表达式开始并直接转到委托类型。 对于要转换为委托实例的lambda表达式,需要为lambda表达式设置一些其他上下文来确定所需的委托类型,例如分配给类型变量,显式转换或(如本例中)a方法重载,其中lambda表达式用于的参数具有与lambda表达式兼容的特定委托类型。

请注意,泛型方法仍有类型推断,其中lambda用于推断类型参数。 Eric Lippert的评论清楚地解释了这一点:

在某些情况下,编译器必须从lambda推断出构造的委托类型。 例如,如果我们有M<A, R>(Func<A, R> f)M((string x) => x.Length)那么编译器将首先从lambda推断出Func<string, something>参数,然后从lambda的主体Func<string, int>

我的观点是编译器不会从头开始推断Func<T, TResult> 正如Eric指出的那样,编译器确实使用lambda来推断类型参数,但编译器仍然需要知道开放泛型类型的上下文。

有关更多详细信息,请阅读C#规范 它将详细说明如何执行重载决策以及管理该命令并将lambda表达式与类型匹配的规则。

补充阅读:
.Net lambda表达式 - 这个参数来自哪里?
为什么不能将匿名方法分配给var?
为什么编译器在这种重载决策情况下不能告诉更好的转换目标? (协方差)
将此委托转换为匿名方法或lambda
并非巧合的是,前三个包括对Eric Lippert撰写的主题和相关问题的精彩讨论,他曾经在Visual Studio C#编译器和语言设计团队工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM