我在玩一个业余项目时,遇到了一个我不理解的类型推断错误。我将其简化为以下的小例子。
我有以下类和函数:
class Foo { }
class Bar { }
class Baz { }
static T2 F<T1, T2>(Func<T1, T2> f) { return default(T2); }
static T3 G<T1, T2, T3>(Func<T1, Func<T2, T3>> f) { return default(T3); }
现在考虑以下示例:
// 1. F with explicit type arguments - Fine
F<Foo, Bar>(x => new Bar());
// 2. F with implicit type arguments - Also fine, compiler infers <Foo, Bar>
F((Foo x) => new Bar());
// 3. G with explicit type arguments - Still fine...
G<Foo, Bar, Baz>(x => y => new Baz());
// 4. G with implicit type arguments - Bang!
// Compiler error: Type arguments cannot be inferred from usage
G((Foo x) => (Bar y) => new Baz());
最后一个例子产生了编译错误,但是我认为它应该能够毫无问题地推断出类型参数。
问题:为什么编译器不能在这种情况下推断出 <Foo, Bar, Baz>
?
更新: 我发现将第二个lambda包装在身份函数中就可以使编译器正确地推断出所有类型。
static Func<T1, T2> I<T1, T2>(Func<T1, T2> f) { return f; }
// Infers G<Foo, Bar, Baz> and I<Bar, Baz>
G((Foo x) => I((Bar y) => new Baz()));
为什么它可以完美地执行所有单独的步骤,但不能一次完成整个推理过程?编译器分析隐式lambda类型和隐式泛型类型的顺序中是否存在一些微妙之处?
(Bar y) => new Baz()
强制转换为Func<Bar, Baz>
(甚至可以省略Bar
中的Bar y
),而不是使用身份函数。这样就可以编译了。 - Rawling