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.

Comments

  1. 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

    ReplyDelete
  2. Johan 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.

    TBH 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

    ReplyDelete
  3. Here is some code that uses what I described in my previous comment:

    program 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.

    ReplyDelete

Post a Comment