C#语言规范在第§7.5.2节中描述了类型推断。其中有一个细节我不太明白。考虑以下情况:
// declaration
void Method<T>(T obj, Func<string, T> func);
// call
Method("obj", s => (object) s);
微软和Mono C#编译器都正确地推断出
T
= object
,但是根据规范中的算法,我的理解会导致T
= string
,然后失败。以下是我的理解:
第一阶段
- 如果Ei是匿名函数,则从Ei到Ti进行显式参数类型推断(§7.5.2.7)。
⇒没有影响,因为lambda表达式没有显式参数类型。对吗?
- 否则,如果Ei具有类型U并且xi是值参数,则从U到Ti进行下限推断。
⇒第一个参数的静态类型为string
,因此这将把string
添加到T
的下限中,对吗?
第二阶段
- 所有不依赖于任何Xj的未固定类型变量Xi都被固定(§7.5.2.10)。
⇒T
未固定;T
不依赖于任何东西...所以T
应该被固定,对吗?
§7.5.2.11 固定
- 候选类型集合Uj最初为Xi边界集合中的所有类型的集合。
⇒{ string
(下限) }
- 然后,我们依次检查Xi的每个边界:[...]对于Xi的每个下限U,从U中没有隐式转换到Uj的所有类型Uj都将从候选集合中删除。 [...]
⇒不会从候选集合中删除任何内容,对吗?
- 如果在剩余的候选类型Uj中有一个唯一的类型V,从这个类型V到所有其他候选类型都有隐式转换,则Xi被固定为V。
⇒由于只有一个候选类型,这是真实的,因此Xi被固定为string
。对吗?
那我错在哪里了?