CoMPi74 3 Posted August 27, 2021 (edited) Hi there, I have a component like this: TCustomEdit<T: record> = class; TOnValidate<T: record> = function (ASender: TCustomEdit<T>; AValue: T): Boolean of object; TCustomEdit<T: record> = class(TEdit) private fOnValidate: TOnValidate<T>; // code here published property OnValidate: TOnValidate<T> read fOnValidate write fOnValidate; end; TIntEdit = class(TCustomEdit<Integer>) // code here end; The code compiles and TIntEdit registers without any complaints. But, when I want to drop the component onto a form, Delphi crashes with AV. What I am missing? I tested it on Delphi XE4 and Delphi 10.4 CE. It's a bug, feature of just "by design"? @Stefan Glienke, will you help? Anyone? Edited August 27, 2021 by CoMPi74 Share this post Link to post
Uwe Raabe 2057 Posted August 27, 2021 Just a guess, but I suspect the Object Inspector cannot cope with the generic event. Share this post Link to post
CoMPi74 3 Posted August 27, 2021 3 minutes ago, Uwe Raabe said: Just a guess, but I suspect the Object Inspector cannot cope with the generic event. I think so too, but it is quite strange, because OnChange of TIntEdit is just TOnChange(ASender: TIntEdit, AValue: Integer). Does not it? Share this post Link to post
Uwe Raabe 2057 Posted August 27, 2021 Strictly speaking it is TOnChange(ASender: TCustomEdit<Integer>; AValue: Integer), but I suspect a general lack of OI support for that. You should file a QP report for that. Share this post Link to post
CoMPi74 3 Posted August 27, 2021 @David Millington, what do you think? It is a bug? Share this post Link to post
Lars Fosdal 1792 Posted August 27, 2021 It's been a while since I tried doing generic based controls, but I think I ran into the same issues. In the end, I changed my approach to using proxy classes that simply hook into the control at runtime and take over its events. Share this post Link to post
darnocian 86 Posted August 27, 2021 I've also had bad experience in the past, and the bug should be re-reported. Does making an 'intermediate' concrete type like the following do anything: TBaseIntEdit = class abstract(TCustomEdit<Integer>); TIntEdit = class(TBaseIntEdit) ... Share this post Link to post
CoMPi74 3 Posted August 27, 2021 1 hour ago, darnocian said: I've also had bad experience in the past, and the bug should be re-reported. Does making an 'intermediate' concrete type like the following do anything: TBaseIntEdit = class abstract(TCustomEdit<Integer>); TIntEdit = class(TBaseIntEdit) ... Nope. It does not change anything 😕 Share this post Link to post
CoMPi74 3 Posted August 27, 2021 It is look like none of a generic property is visible in Object Inspector. But, of course, they are accessible from code. TCustomEdit<T: record> = class; TEvent1 = procedure (AValue: Integer) of object; TEvent2<V: record> = procedure (AValue: V) of object; TEvent3<V: record> = procedure (ASender: TCustomEdit<V>; AValue: V) of object; TCustomEdit<T: record> = class(TEdit) public fEvent1: TEvent1; fEvent2: TEvent2<T>; fEvent3: TEvent3<T>; published property Event1: TEvent1 read fEvent1 write fEvent1; // Accesible from Object Inspector and from code property Event2: TEvent2<T> read fEvent2 write fEvent2; // Only from code property Event3: TEvent3<T> read fEvent3 write fEvent3; // Only from code end; TEditEx = class(TCustomEdit<Integer>); ... RegisterComponents('Test controls', [TEditEx]); BTW. It looks like Delphi (10.4 CE) crashes because of CnMemProfProject wizard (CnPack, v. 1.2.0.1040 Unstable). But it is just an intermediate reason. The AV comes from System.TypInfo.GetPropInfos so definitely something is up. Share this post Link to post
darnocian 86 Posted August 27, 2021 I thought I should try properly to try reproduce as well rather than speculate. 😉 The following worked for me: type TEvent = procedure (avalue:integer)of object; TEvent2<T:record> = procedure (avalue:t) of object; TCustomEdit<T:record> = class(TEdit) private fevent1:tevent; fevent2:TEvent2<integer>; published property event1:tevent read fevent1 write fevent1; property event2:tevent2<integer> read fevent2 write fevent2; end; TEditEx = class(TCustomEdit<integer>) end; ide was fine on my end. Share this post Link to post
CoMPi74 3 Posted August 27, 2021 @darnocian This is not the case I presented. I wanted to have an event handler which generic parameter T is same as in the class definition. I mean fevent2 should be rather TEvent2<T> instead of TEvent2<integer>. Did you try such a case? I did :/ I need it because I want to implement validation mechanism in TCustomEdit<T>.Change method, like in the code below: TEvent<V: record> = procedure (AValue: V) of object; TCustomEdit<T: record> = class(TEdit) public fValue: T; fEvent: TEvent<T>; protected procedure Change; override; published property Event: TEvent<T> read fEvent write fEvent; end; procedure TIMEdit<T>.Change; begin if Assigned(fEvent) then fEvent(fValue); end; Share this post Link to post
Guest Posted August 28, 2021 Sorry, but i think you are missing critical point here 7 hours ago, CoMPi74 said: I mean fevent2 should be rather TEvent2<T> instead of TEvent2<integer>. "TEvent2<T>" does not exist as code to be handled or inspected, while "TEvent2<Integer>" is existing creature, well known and defined. Think of it as a macro or virtual imaginary code, something like "array of", of what ?! Share this post Link to post
Uwe Raabe 2057 Posted August 28, 2021 I beg to disagree here. If it is seen as an invalid construct the compiler should complain. As long as the compiler is fine with such a construct, there are only implementation details in Object Inspector responsible for the crash. There is nothing except missing developer time that should prevent to fix those. We can argue about the priority, though. 1 Share this post Link to post
Guest Posted August 28, 2021 48 minutes ago, Uwe Raabe said: I beg to disagree here. If it is seen as an invalid construct the compiler should complain. As long as the compiler is fine with such a construct, there are only implementation details in Object Inspector responsible for the crash. Can't agree more, that is not a bug with the compiler, but if we need to point to wrong doing or lets call it a bug then it is with the IDE, but on other hand published identifier is essential for the object inspector which we can blame, and it can be warned about by compiler. Share this post Link to post
darnocian 86 Posted August 28, 2021 (edited) 11 hours ago, CoMPi74 said: This is not the case I presented Sorry, I think I was a dufus and didn't pay attention to what i was doing. 😉 Reproducing correctly with event2:TEvent2<T> , the event2 is not exposed as you highlighted... It would be useful to raise the Quality Portal issue so that this type of scenario works... Generics can be really powerful, but unfortunately there are lots of bugs with the implementation. ;( Edited August 28, 2021 by darnocian Share this post Link to post
CoMPi74 3 Posted August 28, 2021 2 hours ago, darnocian said: It would be useful to raise the Quality Portal issue so that this type of scenario works... Done 😉 Here is it: [RSP-34616] Object Inspector does not support generic properties - Embarcadero Technologies 1 Share this post Link to post