Search code examples
delphidelphi-xe6

Print generic array to console


How can I print a generic array to console? This works for simple integer arrays but not for generic ones.

class procedure Print(const A: TArray<Integer>; const Name: String);
var
  I: Integer;
begin
  Write('Array ' + Name +' : ');
  Write('[');
  for I := 0 to High(A) do
  if I <> High(A) then
  begin
    WriteLn(A[I]);
    Write(', ');
  end
  else
  Write(A[I]);
  Write(']');
  WriteLn('');
end;

Solution

  • The Write and Writeln procedures cannot be called with generic arguments. Thus the obvious conclusion is that you need to convert the generic value to a string before calling Write and Writeln.

    This can be achieved using TValue by taking advantage of the following capabilities:

    1. The generic TValue.From<T> method that makes a new TValue instance.
    2. The TValue.ToString method that converts most common types to string.

    So, I think that you are looking for something like this:

    {$APPTYPE CONSOLE}
    
    uses
      System.Rtti;
    
    type
      TMyClass = class
        class procedure Write<T>(const arr: array of T; const Name: string); static;
      end;
    
    class procedure TMyClass.Write<T>(
      const arr: array of T; const Name: string);
    var
      I: Integer;
    begin
      System.Write('Array ' + Name +' : [');
      for I := 0 to high(arr) do begin
        System.Write(TValue.From(arr[i]).ToString);
        if I <> high(arr) then begin
          System.Write(', ');
        end;
      end;
      System.Writeln(']');
    end;
    
    begin
      TMyClass.Write<Integer>([1,2,3,4], 'integer');
      TMyClass.Write<Double>([42.666, 123.4], 'floating point');
      TMyClass.Write<string>(['foo', 'bar'], 'string');
      Readln;
    end.
    

    Output

    Array integer : [1, 2, 3, 4]
    Array floating point : [42.666, 123.4]
    Array string : [foo, bar]
    

    As an aside it really annoys me that I have to create a class to hold these methods. I don't understand why the language designers took that decision.