A lot of times when working with generic arrays I need to know Max length of the arrays I'm working with. For a longtime I was using:
MaxIntValue([Length(Array1), Length(Array2) , Length(Array3)]); // from Math unit
Then I simplified this (to skip typing Length()) with my method:
// array of array of TCardBrand
function GetMaxLength(const aArrays: array of TArrayOfCarBrand): integer;
Works good, but now I want to create a generic MaxLength and I can't make it work with
class function MaxLength<T>(aArrays: array of array of T): integer; - it gives error: [dcc32 Error] Unit2.pas(31): E2029 Identifier expected but 'ARRAY' found
Here is the code what I'm testing, with working example of MaxIntValue from Math unit and example of my method, but extending generic TArray doesn't work:
TCarBrand = record
BrandID: integer;
BrandName: string;
BrandCountry: string;
end;
TArrayOfCarBrand = array of TCarBrand;
TArray = class(System.Generics.Collections.TArray)
public
// ERROR: E2029 Identifier expected but 'ARRAY' found
class function MaxLength<T>(aArrays: array of array of T): integer;
end;
var
vCarsUS, vCarsEU, vCarsJP: TArrayOfCarBrand;
implementation
{$R *.dfm}
class function TArray.MaxLength<T>(aArrays: array of array of T): integer;
var
i: Integer;
begin
Result := 0;
for i := Low(aArrays) to High(aArrays) do
Result := MaxIntValue([Result, Length(aArrays[i])]);
end;
function GetMaxLength(const aArrays: array of TArrayOfCarBrand): integer;
var
i: Integer;
begin
Result := 0;
for i := Low(aArrays) to High(aArrays) do
Result := MaxIntValue([Result, Length(aArrays[i])]);
end;
procedure TForm2.Button1Click(Sender: TObject);
var vMaxLength: integer;
begin
// test lengths
SetLength(vCarsUS,1);
SetLength(vCarsEU,10);
SetLength(vCarsJP,100);
// using MaxIntValue from Math unit - works OK
vMaxLength := MaxIntValue([Length(vCarsUS), Length(vCarsEU), Length(vCarsJP)]);
// using my method GetMaxLength - works OK
vMaxLength := GetMaxLength([vCarsUS, vCarsEU, vCarsJP]);
// trying to set Generic TArray.MaxLength - ERROR
vMaxLength := TArray.MaxLength<TCarBrand>([vCarsUS, vCarsEU, vCarsJP]);
end;
How can I extend generic MaxValue to accept open array of array of < T >?
It's simple enough. Your function does not accept generic arrays, because the parameter list does not attempt to do so. Change it like this.
class function MaxLength<T>(const aArrays: array of TArray<T>): Integer;
The key here is to use TArray<T>
exclusively. This is the generic dynamic array type and using it gives more flexible type compatibility than with array of
dynamic array types. The issues are covered in detail here: What are the reasons to use TArray instead of Array of T?
A consequence of this is that you will need to replace all of your dynamic type declarations and use TArray<T>
instead. In fact you don't need to declare any dynamic array types at all. You can remove all declarations of this form:
type
TFooArray = array of TFoo;
And then replace all occurrences of TFooArray
with TArray<TFoo>
. A side benefit is that you don't need to declare any of the array types and your code becomes less verbose.
I would also comment that there's little point in using MaxIntValue
when you only have two arguments. Use the Max
function then.