Consider the following declaration of a generic utility class in Delphi 2010:
TEnumerableUtils = class
public
class function InferenceTest<T>(Param: T): T;
class function Count<T>(Enumerable: TEnumerable<T>): Integer; overload;
class function Count<T>(Enumerable: TEnumerable<T>; Filter: TPredicate<T>): Integer; overload;
end;
Somehow the compiler type inference seems to have problems here:
var
I: Integer;
L: TList<Integer>;
begin
TEnumerableUtils.InferenceTest(I); // no problem here
TEnumerableUtils.Count(L); // does not compile: E2250 There is no overloaded version of 'Count' that can be called with these arguments
TEnumerableUtils.Count<Integer>(L); // compiles fine
end;
The first call works as expected and T is correctly inferred as Integer.
The second call does not work, unless I also add <Integer
> -- then it works, as can be seen in the third call. Am I doing something wrong or is the type inference in Delphi just not supporting this (I don't think it is a problem in Java which is why expected it to work in Delphi, too).
The compiler would need to do pattern matching to infer parameter types; it currently does not. The compiler is limited to quite simple inference - if the parameter type is of a type parameter type, then the compiler can figure it out, but not much beyond that.
The argument type in your example is not a simple type parameter, but is rather a constructed generic type (it's constructed with the method's type parameter T, but it is constructed none the less). The compiler needs to make two inferences in order to find out the value of T. First, it needs to see that the constructed type's generic type is an ancestor of TList<T>
's generic type; and it also needs to match the type parameter T in the constructed type's type parameter list with the concrete type Integer in TList<T>
's ancestor.
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