PatV 1 Posted April 29, 2022 Hi All,,  Just a silly question 🙂  if I can write this code, what is the pros and cons about it ?  From a lasy view, you don't need to create it, free it, ..  Thanks  Patrick   prTxt = ^rTxt;  rTxt = record  private   FValue : string;   function GetAsText : string;  public   property Value  : string read FValue;   property AsText : string read GetAsText;   function WithValue(const aValue : string) : prTxt;  end;    Share this post Link to post
David Heffernan 2345 Posted April 29, 2022 The final function can't be right. It should be a static class function, but that's not enough. What would it return? A pointer to what instance? You'd need to allocate an instance somewhere.  I'd use a helper record to get around the inability to forward declare value types. Share this post Link to post
PatV 1 Posted April 29, 2022 Hi David, Thanks for your reply ; that's both function (and btw working)  { rTxt } function rTxt.GetAsText: string; begin result:=StringReplace(FValue,'\r\n',CRLF,[rfReplaceAll]); end; function rTxt.WithValue(const aValue: string): prTxt; begin FValue:=aValue; result:=@Self; end;  How should I write it then ?  Share this post Link to post
Chris Rolliston 1 Posted April 29, 2022 37 minutes ago, PatV said: How should I write it then ? What are you aiming to achieve...? Returning a pointer to Self doesn't give any obvious benefit - if the rTxt instance is statically defined, the validity of a pointer to it will remain restricted to the scope of the instance variable. In other words, this sort of code is invalid - function Foo(const Value: string): pTxt; var Inst: rTxt; begin Result := Inst.WriteValue(Value); end; procedure Test; var Ptr: pTxt; begin Ptr := Foo('Bad code - if the next bit "works", it will only be by luck'); ShowMessage(Ptr.AsText); end; Conversely if rTxt is dynamically allocated (New and Dispose standard procedures), then by definition you lose the 'lazy' benefit you hoped to achieve. If your intent was that WriteValue should return a new instance, then (as David said) the method needs to be a class static method (or a constructor), and return the instance type (not a pointer): type fTxt = record // ... class function WriteValue(const Value: String): fTxt; static; end; class function fTxt.WriteValue(const Value: String): fTxt; begin Result.FValue := Value; end; function Foo(const Value: string): fTxt; begin Result := fTxt.WriteValue(Value); end; procedure Test; var Inst: fTxt; begin Inst := Foo('OK code - if next bit works genuinely'); ShowMessage(Inst.AsText); end;  Share this post Link to post
David Heffernan 2345 Posted April 29, 2022 Why return a pointer to self? You just risk having that pointer outlive the record instance.  Make this a constructor or a static class function that returns a new instance.  BTW I remembered wrongly before. No need for a helper to implement a static class function that returns rTxt. Share this post Link to post
darnocian 84 Posted April 29, 2022 (edited) Â I could assume that if the structure in question is more complex and the snippet we see is a sample, the use of withValue() would be part of a bigger set of stuff where the structure is set using method chaining... Â e.g. myrec.withValue('abc').withNum(123)... Â returning a pointer would be slightly more optimal as the delphi syntax should still allow the chaining with the '.', and the original structure would be referenced rather than copies being made if the result of each withXyz() was an actual record. Â if part of the question is about record vs class, well records in Delphi can be heap or stack based, where classes in Delphi are heap based. Assignment of a record in general, even in a method chain would result in copies, vs using a class would simply be passing a pointer around. Â As David mentioned however, it is a trivial scenario, just using a constructor would do. Using method chaining is sometimes an opinion piece, commonly used when using builder type patterns. Edited April 29, 2022 by darnocian Share this post Link to post
PatV 1 Posted April 30, 2022 Yes Darnocian, it was the goal, add fluent interface to record, so the main difference is that passing a record is a copy compare to a class  Thanks  Patrick Share this post Link to post