Just curious
Just curious,
Is there ever a benefit to not providing a GUID in an interface?
(Other than not having to press CTRL+Shift+G ;-)
E.g.: faster code, smaller memory footprint, anything else?
I can't think of anything, but don't have the evidence to back up the claim.
Is there ever a benefit to not providing a GUID in an interface?
(Other than not having to press CTRL+Shift+G ;-)
E.g.: faster code, smaller memory footprint, anything else?
I can't think of anything, but don't have the evidence to back up the claim.
Given the automatic GUID isn't really working, removing the fixed one seems a fairly bad idea.... We could revisit in the future, but not sure this is the best option
ReplyDeleteJohan Bontes Compiler cannot just randomly assign guids. It needs to do so in a deterministic way. And that might be more complicated than you think.
ReplyDeleteTBH I would rather improve interface casting to check the type rather than the guid (which is possible since XE when class typeinfo contains the typeinfo of its implementing interfaces rather than only the guids, see System.TInterfaceTable). That again would also mean that typeinfo needs to be somehow similar across modules. Currently this is not the case as I blogged about some while ago - see http://delphisorcery.blogspot.de/2017/02/generics-modules-and-typeinfo.html
Here is some code that uses what I described in my previous comment:
ReplyDeleteprogram Project1;
{$APPTYPE CONSOLE}
uses
SysUtils, TypInfo;
type
IFoo = interface
['{AF1CAEA8-2CE2-4A44-BF28-72201A9BE305}']
end;
TFoo = class(TInterfacedObject, IFoo)
end;
TType = record // no generic standalone routines, ughhh
class function Supports(const intf: IInterface): Boolean; static;
end;
// copied from Spring.pas
function GetInterfaceEntry(cls: TClass; intf: PTypeInfo): PInterfaceEntry;
type
PPPTypeInfo = ^PPTypeInfo;
var
intfGuid: TGUID;
interfaceTable: PInterfaceTable;
p: PPPTypeInfo;
i: Integer;
begin
intfGuid := intf.TypeData.Guid;
repeat
interfaceTable := cls.GetInterfaceTable;
if interfaceTable <> nil then
begin
p := @interfaceTable.Entries[interfaceTable.EntryCount];
for i := 0 to interfaceTable.EntryCount - 1 do
begin
Result := @interfaceTable.Entries[i];
if p^^ = intf then
Exit;
Inc(p);
end;
end;
cls := cls.ClassParent;
until cls = nil;
Result := nil;
end;
class function TType.Supports(const intf: IInterface): Boolean;
var
obj: TObject;
begin
obj := intf as TObject;
if Assigned(obj) then
Result := GetInterfaceEntry(obj.ClassType, TypeInfo(T)) <> nil
else
Result := False;
end;
var
i: IInterface;
begin
i := TFoo.Create;
try
// Assert(not Supports(i, IFoo)); // fails
Assert(not TType.Supports>(i));
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
However as I mentioned this only works within the same module as otherwise typeinfo addresses are differently as each module contains their own.