.NET 4.0 MS-C# コンパイラの自動型推論が失敗し、型を「手動で」指定しなければならないケースに出くわしました。
これは私にとって大きな問題ではありませんが、コンパイラが呼び出しの正しい型を自動的に見つけられない理由を知りたいと思うには十分です..
呼び出しを次のプログラムに減らしました。
class Program
{
interface GenericInterface<T> { }
interface Covariant<out T> { }
static void Fn<T, U>(GenericInterface<T> t, U u)
where T : Covariant<U>
{
}
class Base { }
class Derived : Base { }
static void Main(string[] args)
{
Base b = null;
Derived d = null;
GenericInterface<Covariant<Base>> c = null;
Fn(c, b); // 1
Fn<Covariant<Base>, Base>(c, d); // 2
Fn(c, d); // 3
}
}
"// 3" とマークされた Complex への最後の呼び出しのため、コードはコンパイルされません。
最初の呼び出しは簡単で簡単です。ベース/サブクラスは関係ありません。2 番目の呼び出しでは、すべてのパラメーターを「手動で」指定するだけです。
コンパイラーが、2 番目の呼び出しで使用されたパラメーターを 3 番目の呼び出しでも自動的に選択することを期待していました。確かに、2 番目のパラメーターは実際には "Derived" として指定されますが、これは "Base" に変換でき、最初のパラメーターは U が "Base" 型である必要があります。インターフェースの共変型のため、「ベース」を U として where 句を使用できるはずです。
C# でのジェネリック型パラメーター推定のルールは正確にはわかりませんが、「パラメーターの代入が 1 つしかない場合は、これを使用し、そうでない場合はコンパイルを拒否する」のように機能すると常に想定していました。
コンパイラが型を自動的に検出しないのはなぜですか? これは、「コンパイラがこれを行うことができれば、フェルマーの最終定理も解決できなければならない」ケースの 1 つですか? :D