Type-Inference in Generic Methods
17. February 2021 by Olaf Monien
Due to an interesting code example, behind which Для просмотра ссылки Войдиили Зарегистрируйся first suspected a possible bug in the Delphi compiler, I took a closer look at the calling behavior of overloaded methods that also contain generic type parameters. I was surprised by the possible bug since I use overloads with combinations of generic and non-generic methods in current projects without any obvious errors.
Here is a simplified version of Kim’s code:
Which of the two possible variants of DoSomething should be called by Foo.DoSomething(Bar)?
At a first glance, I was inclined to say that the non-generic variant, i.e. function DoSomething(SomeObject: TValue): string; should be called, since after all no type parameter is specified and therefore the first variant matches best.
But in fact, the generic, second variant is called. I initially suspected “TValue” of “blocking” the overload resolution here, since TValue is actually an “artificial” RTTI.driven type.
Для просмотра ссылки Войдиили Зарегистрируйся came up with the correct hint:
Generic parameters are actually optional and the type is automatically inferred by the type of the variable that is passed. This “type inference” takes precedence over overload resolution and thus produces a better match than the “TValue” method.
Type-inference of generic methods Для просмотра ссылки Войдиили Зарегистрируйся btw.
So the following code actually calls a generic implementation, although no type parameter is specified in the call:
Here is a Gist with full code to try:
Для просмотра ссылки Войдиили Зарегистрируйся
17. February 2021 by Olaf Monien
Due to an interesting code example, behind which Для просмотра ссылки Войди
Here is a simplified version of Kim’s code:
Код:
TFoo = class(TObject)
public
function DoSomething(SomeObject: TValue): string; overload;
function DoSomething<T>(SomeObject: T): string; overload;
end;
TBar = class(TObject)
end;
//...
var Foo := TFoo.Create;
var Bar := TBar.Create;
Foo.DoSomething(Bar);
At a first glance, I was inclined to say that the non-generic variant, i.e. function DoSomething(SomeObject: TValue): string; should be called, since after all no type parameter is specified and therefore the first variant matches best.
But in fact, the generic, second variant is called. I initially suspected “TValue” of “blocking” the overload resolution here, since TValue is actually an “artificial” RTTI.driven type.
Для просмотра ссылки Войди
Generic parameters are actually optional and the type is automatically inferred by the type of the variable that is passed. This “type inference” takes precedence over overload resolution and thus produces a better match than the “TValue” method.
Type-inference of generic methods Для просмотра ссылки Войди
So the following code actually calls a generic implementation, although no type parameter is specified in the call:
Код:
function DoSomething<T>(SomeObject: T): string;
//...
Foo.DoSomething(Bar); //<T> is inferred from "Bar"
Для просмотра ссылки Войди