I'm getting a strange error with Visual Studio 10 (and now 11 as well). I have an extension method
public static S Foo<S, T>(this S s) where S : IEnumerable<T>
{
return s;
}
Now if I call
"".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?)
I'm not at all understanding what's happening under hood. The annoying part is that the intellisense lists Foo
for IEnumberable<T>
s. At best it should have given a type can't be inferred error
.
If I call it this way:
Extension.Foo(""); // => The type arguments for method 'Extension.Foo<S,T>(S)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Why cannot type be inferred in the above case?
More:
Suppose I have:
public static S Foo<S, T>(this S s, T t) where S : IEnumerable<T>
{
return s;
}
And if I call:
"".Foo(1);
The type inference is so smart here to tell me that Foo
should be returning IEnumerable<int>
and string
is not all that!!
So if compiler can know Foo
is expecting a char as the first argument, then why doesn't my first example just compile? In other words why is that in the first example the compiler know T
in that case is char?
As expectedly this works for the second example:
"".Foo('l');
I'm just wondering why can't T
be inferred as char
in first example, after all string is IEnumberable<char>
.
I got the answer from SLaks. But it's so strange that C# doesn't do this (kind of type inference) considering compiler takes into account the generic constraints as well when exposing the available methods to operate on an object.
In other words:
public static S Foo<S, T>(this S s)
{
return s;
}
makes Foo
available on all object
s.
public static S Foo<S, T>(this S s) where S : IEnumerable<T>
{
return s;
}
makes Foo
available on all IEnumerable<T>
s since it knows S
is IEnumerable<T>
. So I was thinking C# will be even inferring the type of T
! Thanks everyone! ;)
The type inference engine isn't smart enough to do that.
C# type inference only looks at the method signature.
Generic constraints are not part of the signature.
Since T
is not used directly in the signature, the compiler will not infer it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With