Why does the following generate an error in Delphi (XE)?
unit UTest;
interface
type
TTest = class
public
procedure Foo<T>(A: T);
end;
implementation
{ TTest }
procedure TTest.Foo<T>(A: T);
begin
A.Add('hej');
end;
end.
I thought that generic types in Delphi was simply inserted into the generic function, so it would only error out if used with a type which don't have an Add(string) method.
To call a generic method, you need to provide types that will be used during the method invocation. Those types can be passed as an instance of NType objects initialized with particular . NET types.
Luckily, this is quite easy to do with the help of reflection. The first step to dynamically invoking a generic method with reflection is to use reflection to get access to the MethodInfo of the generic method. To do that simply do this: var methodInfo = typeof(ClassWithGenericMethod).
You need to use reflection to get the method to start with, then "construct" it by supplying type arguments with MakeGenericMethod: MethodInfo method = typeof(Sample). GetMethod(nameof(Sample. GenericMethod)); MethodInfo generic = method.
Dynamically invokes a method whose name and parameters must be set at run time. The Invoke( ) method is one of several reflection methods of the Progress. Lang. Class class that provide type information about a class or interface at run time.
Your code produces a compilation error because the compiler has no way of knowing that T
has a method named Add
that receives a single string parameter.
I thought that generic types in Delphi was simply inserted into the generic function, so it would only error out if used with a type which don't have an Add(string) method.
If you were using Smalltalk or C++ templates, then your assumption would be accurate. However, generics are not the same as templates. For generics you need to apply a constraint to the type parameter. The constraint needs to tell the compiler what properties T
must have.
For example, you could constrain T
to be derived from a class that has a suitable Add
method. Or you could constrain T
to implement an interface with a suitable Add
method.
Documentation link for Delphi generic constraints: http://docwiki.embarcadero.com/RADStudio/en/Constraints_in_Generics
The generic constraints that can be applied are rather limited, which is something of a shame. For example, I'd love to be able to constrain a type to have certain mathematical operators. For example, I'd like to be able to constrain a type to have +
and -
operators, say. However, there are pros and cons to both generics and templates, and so I do accept that these limitations are the result of a justifiable design decision by the Delphi language designers.
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