I'm writing some utility code for an old Delphi XE codebase; in order to keep things simpler and safer I've created a method meant to wrap a type-specific TProc<TReq>
(where TReq
is a generic class type) passed via parameters in a more broad TProc<TObject>
that should be fed to a third-party component later on, along with TClass(TReq)
and an additional string argument:
type
TREvoHostConnectionOptions = record
// [...]
procedure OnPush<TReq:class>(const pushMethod: string; const action: TProc<TReq>);
end;
// [...]
procedure TREvoHostConnectionOptions.OnPush<TReq>(const pushMethod: string; const action: TProc<TReq>);
var
rec: TRPushHandler;
begin
rec.PushMethod := pushMethod;
rec.PushModel := TClass(TReq);
rec.Handler :=
procedure(reqRawModel: TObject)
var
reqModel: TReq;
begin
// Conversione modello richiesta
reqModel := reqRawModel as TReq;
if Assigned(reqRawModel) and not Assigned(reqModel) then
raise EEvoHostException.Create(Format('Impossibile convertire il modello di tipo %s in %s.', [reqRawModel.ClassName, TClass(TReq).ClassName]));
// Azione
if Assigned(action) then
action(reqModel);
end;
PushHandlers.Add(rec);
end;
The previous method compiles successfully and if invoked like this, works as intended (although, having TObject
as the generic type defeats the purpose of the method):
opts.OnPush<TObject>('Test', procedure (reqModel: TObject) begin (* ... *) end);
However, if in the testing form unit I invoke it with a specifically crafted model class:
type
TTestModel = class(TObject)
strict private
_a, _b: string;
public
property A: string read _a write _a;
property B: string read _b write _b;
end;
I get the following compiler error in a completely irrelevant line (and completely different and totally unrelated method) in the calling unit:
[DCC Error] WndMain.pas(96): E2010 Incompatible types: 'TTestModel' and 'TObject'
* The displacement only occurs with this specific error, if I introduce an artificial syntax error anywhere else in the same file it gets reported at the correct line.
Any thoughts? Is this a compiler bug, and if so is there any way to get around it? Unfortunately I can't remove the :class
constraint on the method because otherwise the TClass(TReq)
conversion that happens inside the method raises (logically) another compilation error about TReq
not being a constrained class or interface type.
Exception.Create(Format('Error %d', [123]))
, tryException.CreateFmt('Error %d', [123])
. - Andreas Rejbrand