user3764855
user3764855

Reputation: 297

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;

Upvotes: 2

Views: 2753

Answers (1)

David Heffernan
David Heffernan

Reputation: 612964

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.

Upvotes: 6

Related Questions