Search code examples
delphiconstructorrecord

Delphi: Record constructor vs factory function


So what will be the preferred way of initializing records?

With a 'factory function':

TMyRecord = record
  valueX: integer;
  valueY: integer;
end;

function MyRecord(const AValueX, AValueY: integer): TMyRecord;
begin
  result.valueX := AValueX;
  result.valueY := AValueY;
end;

var
  myrec: TMyRecord;
begin
  myrec := MyRecord(1, 2);
end;

or a constructor:

TMyRecord = record
  valueX: integer;
  valueY: integer;
  constructor Create(const AValueX, AValueY: integer);
end;

constructor TMyRecord.Create(const AValueX, AValueY: integer);
begin
  self.valueX := AValueX;
  self.valueY := AValueY;
end;

var
  myrec: TMyRecord;
begin
  myrec := TMyRecord.Create(1, 2);
end;

I feel that the constructor things more encapsulated, but it makes it easy to get confused when reading code. It makes it look like a class that lack a call to free. It's also more to type...

Why would you prefer one over the other?


Solution

  • I prefer classes, but if I have to use records, I like to treat them as similar as classes as possible. So I use the record constructor.

    But there is an annoying bug with records and units. If a function returns a record (with methods), it produces an internal error if you want to access these methods. You can circumvent this by assigning it to another variable:

    type 
      TMyRec = record
        ..
        procedure X;
      end;
    
    
    function GetRec: TMyRec;
    
    
    
    procedure Test;
    var
      r1, r2 : TMyRec;
    begin
      r1 := GetRec;
      r1.X; // internal error
      r2 := r1;
      r2.X; // No internal error;