This example can be simplified like so, removing all reference to generics:
{$APPTYPE CONSOLE}
var
x, y: array of Integer;
begin
SetLength(x, 1);
x[0] := 42;
y := x;
Writeln(x[0]);
y[0] := 666;
Writeln(x[0]);
end.
The output is:
42
666
The reason for this is that a dynamic array is a reference type. When you assign to a variable of dynamic array type, you are taking another reference and not making a copy.
You can resolve this by forcing a reference to be unique (that is have just a simple reference). There are a number of ways to achieve this. For instance, you can call SetLength
on the array that you want to be unique.
{$APPTYPE CONSOLE}
var
x, y: array of Integer;
begin
SetLength(x, 1);
x[0] := 42;
y := x;
SetLength(y, Length(y));
Writeln(x[0]);
y[0] := 666;
Writeln(x[0]);
end.
Output:
42
42
So, in your code you can write it like this:
MyList:=TList<TMyRec>.Create;
SetLength(MyRec.MyArr,5);
MyRec.MyArr[0]:=8; // just for demonstration
MyRec.Name:='Record 1';
MyRec.Completed:=true;
MyList.Add(MyRec);
SetLength(MyRec.MyArr,5); // <-- make the array unique
MyRec.MyArr[0]:=5; // just for demonstration
MyRec.Name:='Record 2';
MyRec.Completed:=false;
MyList.Add(MyRec);
You can use a variety of other ways to enforce uniqueness, including Finalize
, assigning nil
, Copy
, etc.
This issue is covered in some detail in the documentation. Here are the pertinent excerpts:
If X and Y are variables of the same dynamic-array type, X := Y points
X to the same array as Y. (There is no need to allocate memory for X
before performing this operation.) Unlike strings and static arrays,
copy-on-write is not employed for dynamic arrays, so they are not
automatically copied before they are written to. For example, after
this code executes:
var
A, B: array of Integer;
begin
SetLength(A, 1);
A[0] := 1;
B := A;
B[0] := 2;
end;
the value of A[0] is 2. (If A and B were static arrays, A[0] would
still be 1.) Assigning to a dynamic-array index (for example,
MyFlexibleArray[2] := 7) does not reallocate the array. Out-of-range
indexes are not reported at compile time. In contrast, to make an
independent copy of a dynamic array, you must use the global Copy
function:
var
A, B: array of Integer;
begin
SetLength(A, 1);
A[0] := 1;
B := Copy(A);
B[0] := 2; { B[0] <> A[0] }
end;