理解できない型推論エラーに出くわしたとき、趣味のプロジェクトで遊んでいました。私はそれを次の簡単な例に単純化しました。
私は次のクラスと関数を持っています:
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>
この場合、コンパイラが推測できないのはなぜですか?
更新: 2番目のラムダを恒等関数でラップするだけで、コンパイラーがすべての型を正しく推測することを発見しました。
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()));
なぜそれはすべての個々のステップを完全に行うことができますが、一度にすべての推論を行うことはできませんか?コンパイラが暗黙のラムダ型と暗黙のジェネリック型を分析する順序に微妙な点はありますか?