HaSo4 0 Posted January 15 Good day, I noticed that under D11.3, at Data.Bind.Components.pas, that the GUID is the same. Usually I would consider that as an error, but with the inherited interfaces I'm unsure, if there is probably a deeper purpose or hack behind: IBindCompFactoryContext = interface ['{E0FB570F-2EF0-44C7-BD19-F4F8ACAE2294}'] function GetDesigner: IInterface; function GetControlComponent: TComponent; function GetOwner: TComponent; function GetBindingsList: TCustomBindingsList; property BindingsList: TCustomBindingsList read GetBindingsList; property Owner: TComponent read GetOwner; property ControlComponent: TComponent read GetControlComponent; property Designer: IInterface read GetDesigner; end; IBindCompFactoryExecuteContext = interface(IBindCompFactoryContext) ['{E0FB570F-2EF0-44C7-BD19-F4F8ACAE2294}'] function UniqueName(const ABaseName: string): string; procedure BindCompCreated(AComponent: TComponent); end; Please give me some more insights, if there were any. Share this post Link to post
DelphiUdIT 176 Posted January 15 (edited) You must use GUIDs when there is a need to use RTTI "as" and "is". Like you told, each interface should have a unique GUID, but I have already see that. Start from here: https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Object_Interfaces_(Delphi) (may be the link is wrong ... wiki is down at the time of writing) P.S.: You can read also these books (with examples) - Hodges Nick - Coding in Delphi (year 2013) - Hodges Nick - More Coding in Delphi (year 2015) I don't know if there are something that can help you ... Edited January 15 by DelphiUdIT Share this post Link to post
dummzeuch 1505 Posted January 15 (edited) Since these interfaces are not identical they should have different GUIDs. If only one of them (IBindCompFactoryExecuteContext) is ever instantiated, only this one should have a GUID. So yes, that's a bug. Probably caused by copy and paste, as most of these errors. Edited January 15 by dummzeuch 2 Share this post Link to post
HaSo4 0 Posted January 16 Thank you, then I'm reassured that my world of interface GUIDs is still intact. Share this post Link to post
David Heffernan 2345 Posted January 16 14 hours ago, DelphiUdIT said: You must use GUIDs when there is a need to use RTTI "as" and "is". Like you told, each interface should have a unique GUID, but I have already see that. Start from here: https://docwiki.embarcadero.com/RADStudio/Alexandria/en/Object_Interfaces_(Delphi) (may be the link is wrong ... wiki is down at the time of writing) P.S.: You can read also these books (with examples) - Hodges Nick - Coding in Delphi (year 2013) - Hodges Nick - More Coding in Delphi (year 2015) I don't know if there are something that can help you ... I think the asker knows what GUIDs are used for. However the question is whether the use of the same GUID for two distinct interfaces is a bug or not. Share this post Link to post
DelphiUdIT 176 Posted January 16 9 minutes ago, David Heffernan said: I think the asker knows what GUIDs are used for. However the question is whether the use of the same GUID for two distinct interfaces is a bug or not. I agree with you, I just wanted to point out some sources on where to possibly look for further useful information on the topic. I've already seen double GUIDs in interfaces in COM environments, and they worked correctly (or at least I never detected problems), but I never looked into them further. Share this post Link to post
David Heffernan 2345 Posted January 16 2 hours ago, DelphiUdIT said: or at least I never detected problems ^^^^^^^^^ Share this post Link to post
HaSo4 0 Posted January 16 3 hours ago, DelphiUdIT said: or at least I never detected problems I'm pretty sure they will show problems, when both interfaces need's to be accessed via Rtti both. Perhaps it is just a lucky coincidence that both interfaces have not yet been used via Rtti. In any case, this is not an acceptable condition to me, and it's clear that it's not a clever hack. Thanks for your help to clarify this topic anyway. Share this post Link to post
Stefan Glienke 2002 Posted January 16 (edited) RTTI does have nothing to do with it but TObject.GetInterfaceEntry - try the following code: type IFoo = interface ['{5DEC09C5-FADC-46A5-814F-9ED91259A37F}'] function GetFooName: string; end; IBar = interface ['{5DEC09C5-FADC-46A5-814F-9ED91259A37F}'] function GetBarName: string; end; TFooBar = class(TInterfacedObject, IFoo, IBar) function GetFooName: string; function GetBarName: string; end; function TFooBar.GetFooName: string; begin Result := 'Foo'; end; function TFooBar.GetBarName: string; begin Result := 'Bar'; end; var i: IInterface; begin i := TFooBar.Create; Writeln((i as IFoo).GetFooName); Writeln((i as IBar).GetBarName); end. The interesting thing with those two interfaces in the RTL is that coincidentally they will not cause any harm because of how they are implemented and related to each other - the one inherits from the other and they are also implemented by classes that inherit from each other. Edited January 16 by Stefan Glienke 1 Share this post Link to post
Kas Ob. 121 Posted January 16 6 minutes ago, Stefan Glienke said: RTTI does have nothing to do with it but TObject.GetInterfaceEntry - try the following code: Great example ! and i want to expand on this a little System.SysUtils; type IFoo = interface ['{5DEC09C5-FADC-46A5-814F-9ED91259A37F}'] function GetFooName: string; end; IBar = interface ['{5DEC09C5-FADC-46A5-814F-9ED91259A37F}'] procedure Dummy; function GetBarName: string; end; TFooBar = class(TInterfacedObject, IFoo, IBar) function GetFooName: string; function GetBarName: string; procedure Dummy; end; function TFooBar.GetFooName: string; begin Result := 'Foo'; end; procedure TFooBar.Dummy; begin Writeln('Dummy called !'); // this is procedure without result ! // yet it might don't raise an exception here because the result in a register could be 0 or valid value end; function TFooBar.GetBarName: string; begin Result := 'Bar'; end; var i: IInterface; begin i := TFooBar.Create; Writeln((i as IFoo).GetFooName); Writeln((i as IBar).GetBarName); Readln; end. The result Dummy called ! Bar 1 Share this post Link to post
DelphiUdIT 176 Posted January 16 (edited) 4 hours ago, Stefan Glienke said: RTTI does have nothing to do with it but TObject.GetInterfaceEntry - try the following code: ...... .... The interesting thing with those two interfaces in the RTL is that coincidentally they will not cause any harm because of how they are implemented and related to each other - the one inherits from the other and they are also implemented by classes that inherit from each other. Uhmmm for me it's not working, but maybe I'm missing something... I'm almost certain that the "as" and "is" don't work if the GUIs are identical... Edited January 16 by DelphiUdIT Share this post Link to post
Stefan Glienke 2002 Posted January 16 (edited) That was the point to show how it gives you the wrong one if two interfaces have the same GUID. The interfaces and their implementation in the RTL inherit from each other so their IMT overlap and the implementations don't differ between those two so there is does not matter. Simply try that for yourself by inheriting one of the interfaces in my example from the other. Edited January 16 by Stefan Glienke Share this post Link to post
DelphiUdIT 176 Posted January 16 (edited) May be, now is working, like the example in the Embarcadero unit .... but there are some facets to evaluate. program Project2; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; type IFoo = interface ['{5DEC09C5-FADC-46A5-814F-9ED91259A37F}'] function GetEmptyName: string; function GetFooName: string; end; IBar = interface(IFoo) ['{5DEC09C5-FADC-46A5-814F-9ED91259A37F}'] function GetBarName: string; end; //TFooBar = class(TInterfacedObject, IBar) //This is working too TFooBar = class(TInterfacedObject, IFoo, IBar) function GetEmptyName: string; function GetFooName: string; function GetBarName: string; end; function TFooBar.GetEmptyName: string; begin Result := 'Empty'; end; function TFooBar.GetFooName: string; begin Result := 'Foo'; end; function TFooBar.GetBarName: string; begin Result := 'Bar'; end; var i: IInterface; begin try { TODO -oUser -cConsole Main : Insert code here } i := TFooBar.Create; Writeln((i as IFoo).GetEmptyName); Writeln((i as IFoo).GetFooName); Writeln((i as IBar).GetBarName); except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; readln; end. Edited January 16 by DelphiUdIT Share this post Link to post