在较高的层次上,方法类型推断是这样工作的。
首先我们列出所有的论据-- 您提供的表达式 -- 及其相应的形式参数类型.
让我们看一个比您给出的更有趣的例子。假设我们有
class Person {}
class Employee : Person {}
...
Person p = whatever;
Employee p2 = whatever;
和同一个电话。所以我们进行对应:
p --> T1
p2 --> T1
5 --> T2
然后我们列出每个类型参数的“边界”以及它们是否“固定”。我们有两个类型参数,并且一开始就没有上限、下限或精确边界。
T1: (unfixed) upper { } lower { } exact { }
T2: (unfixed) upper { } lower { } exact { }
(回想一下我们最近在另一个问题中讨论的类型的相对大小取决于类型是否具有更多或更少的限制性;限制性更强的类型是smaller比限制较少的一种。长颈鹿比动物小,因为动物比长颈鹿多。 “上”和“下”界集正是这样的:给定类型参数的类型推断问题的解必须是大于或等于每个下界和小于或等于每个上限,以及相同每个精确的界限。)
然后我们查看每个参数及其对应的类型。 (如果参数是 lambda,那么我们可能必须弄清楚order我们在其中查看参数,但这里没有任何 lambda,所以让我们忽略该细节。)对于每个参数,我们都会创建一个推理到形式参数类型,并将我们推断出的事实添加到绑定集。因此,在查看第一个参数之后,我们推断出界限:
T1: (unfixed) upper { } lower { Person } exact { }
T2: (unfixed) upper { } lower { } exact { }
在第二个参数之后我们推断出界限
T1: (unfixed) upper { } lower { Person, Employee } exact { }
T2: (unfixed) upper { } lower { } exact { }
在第三个参数之后,我们推导出边界:
T1: (unfixed) upper { } lower { Person, Employee } exact { }
T2: (unfixed) upper { } lower { int } exact { }
在我们取得尽可能多的进展后,我们通过找到边界集中满足每个边界的最佳类型.
对于T1,边界集中有两种类型,Person
and Employee
。其中是否有一个满足所设定的边界中的每个边界?是的。Employee
不满足Person
绑定因为Employee
是一个比以下类型更小的类型Person
; Person
is a 下限- 它的意思是没有类型小于Person
是合法的. Person
确实满足所有界限:Person
与Person
并且大于Employee
,因此它满足两个界限。 T1 的边界集中满足每个边界的最佳类型是Person
对于 T2 显然是int
因为 T2 的边界设置中只有一种类型。所以我们然后修复类型参数:
T1: (fixed) Person
T2: (fixed) int
然后我们问“每个类型参数都有固定的界限吗?”答案是“是”,因此类型推断成功。
如果我将第一个参数的类型更改为dynamic
那么T1是如何推断的呢?
如果任何参数是动态的,则 T1 和 T2 的推理将推迟到运行时,此时语义分析器会考虑最派生的可访问运行时类型值的类型作为动态参数提供的下界。
如果您对这个主题感兴趣并且想要了解更多信息,这里有一个我解释该算法的 C# 3 版本的视频:
http://blogs.msdn.com/b/ericlippert/archive/2006/11/17/a-face-made-for-email-part- Three.aspx
(C# 3 没有上限,只有下限和精确限;除此之外,算法几乎相同。)
我写的许多关于类型推断问题的文章都在这里:
http://blogs.msdn.com/b/ericlippert/archive/tags/type+inference/