Visual Studio 10(および現在は11)で奇妙なエラーが発生します。拡張メソッドがあります
public static S Foo<S, T>(this S s) where S : IEnumerable<T>
{
return s;
}
今私が電話すると
"".Foo(); // => 'string' does not contain a definition for 'Foo' and no extension method 'Foo' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?)
私はボンネットの下で何が起こっているのか全く理解していません。厄介な部分は、インテリセンスがsをリストFoo
するIEnumberable<T>
ことです。せいぜい、それはを与えるべきでしたtype can't be inferred error
。
私がそれをこのように呼ぶならば:
Extension.Foo(""); // => The type arguments for method 'Extension.Foo<S,T>(S)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
上記の場合、なぜ型推論できないのですか?
もっと:
私が持っているとしましょう:
public static S Foo<S, T>(this S s, T t) where S : IEnumerable<T>
{
return s;
}
そして私が呼ぶなら:
"".Foo(1);
型推論はここではとても賢いので、戻ってFoo
くるはずであり、それだけではありません!!IEnumerable<int>
string
それで、コンパイラーがFoo
最初の引数としてcharを期待していることを知ることができるなら、なぜ私の最初の例は単にコンパイルされないのですか?言い換えれば、最初の例でコンパイラがT
その場合にcharであることを知っているのはなぜですか?
予想通り、これは2番目の例で機能します。
"".Foo('l');
結局のところ、文字列が。であるのに、なぜ最初の例のT
ように推測できないのか疑問に思っています。char
IEnumberable<char>
編集:
SLaksから答えを得ました。しかし、コンパイラがオブジェクトを操作するために使用可能なメソッドを公開するときにジェネリック制約も考慮に入れることを考慮して、C#がこれ(型推論の一種)を行わないのは非常に奇妙です。
言い換えると:
public static S Foo<S, T>(this S s)
{
return s;
}
すべてのでFoo
利用可能になりますobject
。
public static S Foo<S, T>(this S s) where S : IEnumerable<T>
{
return s;
}
がであることがわかっているため、Foo
すべてので使用可能になります。だから私はC#がタイプを推測することさえできるだろうと思っていました!みんな、ありがとう!;)IEnumerable<T>
S
IEnumerable<T>
T