Can array types have methods?

I defined the type of the dynamic array as follows:

TMyIntegerArray = array of integer: 

I would like to use the IndexOf function, as I would if it were a descendant of TObject :

 var MyArray : TMyIntegerArray; i : integer: begin //... i := MyArray.IndexOf(10); //... end; 

Currently, the only solution I have found is to write a function that takes an array and a target value as parameters:

 function IndexOf(AArray : TMyIntegerArray; ATargetValue : integer; AOffset : integer = 0); begin Result := AOffset; while(Result < Length(AArray)) do begin if(AArray[Result] = ATargetValue) then Exit; Result := Result + 1; end; Result := -1; end; 

Can a TMyIntegerArray type have a function like IndexOf ?

Additional Information:

I am currently using Delphi2007, but I am also interested to find out if there is a way to add methods to array types in newer versions of Delphi.

+5
source share
3 answers

In newer versions of Delphi (XE3 +), you can implement methods for array types using record helpers :

 program ProjectTest; {$APPTYPE CONSOLE} Type TMyArray = array of integer; TMyArrayHelper = record helper for TMyArray procedure Print; function IndexOf(ATargetValue : integer; AOffset : integer = 0): Integer; end; procedure TMyArrayHelper.Print; var i: Integer; begin for i in Self do WriteLn(i); // Use Self for variable reference end; function TMyArrayHelper.IndexOf(ATargetValue : integer; AOffset : integer = 0): Integer; begin Result := AOffset; while(Result < Length(Self)) do begin if(Self[Result] = ATargetValue) then Exit; Result := Result + 1; end; Result := -1; end; var myArr : TMyArray; begin myArr := [0,1,2]; // A neat way to populate a dynamic array (XE7+) myArr.Print; WriteLn(myArr.IndexOf(2)); ReadLn; end. 

Note. . You can skip the type declaration of TMyArray and use the TArray<Integer> for a more relaxed type resolution. As always with write helpers, there can only be one helper to the type (and the one that will be used is the closest to the area).

This type of helper is called a built-in type helper , where the compiler places an implicit record structure around the type.

+13
source

Although LU RD showed a direct solution to your question, I'm going to add a slightly different generic approach. This has the advantage of providing the right solution for different types of arrays in one place.

In versions of Delphi that support generics, you can use the method used in TArray, found in System.Generics.Collections. This is a direct extension of this class introducing the IndexOf function:

 type TArrayExt = class(TArray) public class function IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index, Count: Integer): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T): Integer; overload; static; end; class function TArrayExt.IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index, Count: Integer): Integer; var I: Integer; begin if (Index < Low(Values)) or ((Index > High(Values)) and (Count > 0)) or (Index + Count - 1 > High(Values)) or (Count < 0) or (Index + Count < 0) then raise EArgumentOutOfRangeException.CreateRes(@SArgumentOutOfRange); if Count = 0 then begin Exit(-1); end; for I := Index to Index + Count - 1 do begin if Comparer.Equals(Item, Values[I]) then begin Exit(I); end; end; Result := -1; end; class function TArrayExt.IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>): Integer; begin Result := IndexOf<T>(Values, Item, Comparer, Low(Values), Length(Values)); end; class function TArrayExt.IndexOf<T>(const Values: array of T; const Item: T): Integer; begin result := IndexOf<T>(Values, Item, TEqualityComparer<T>.Default, Low(Values), Length(Values)); end; 

A simple use case might look like this:

 procedure Main; var arr: TArray<Integer>; N: Integer; begin arr := TArray<Integer>.Create(5, 7, 3, 4, 2); repeat Readln(N); N := TArrayExt.IndexOf(arr, N); Writeln(N); until false; end; 
+5
source

For Delphi 2009 and above, you can use the general list:

 uses System.Generic.Collections; var MyArray : TList<integer>; i : integer; begin MyArray := TList<integer>.Create; MyArray.Add(3); MyArray.Add(7); MyArray.Add(10); i := MyArray.IndexOf(10); end; 

In Delphi 2007, you can use a custom entry:

 type TMyArray = record private TheArray : array of integer; public procedure Add(Value : integer); function IndexOf(Value : integer) : integer; function Length : integer; end; procedure TMyArray.Add(Value : integer); var i : integer; begin i := length(TheArray); setlength(TheArray,i+1); TheArray[i] := Value; end; function TMyArray.IndexOf(Value : integer) : integer; var i : integer; begin for i := 0 to length(TheArray)-1 do begin if TheArray[i] = Value then begin Result := i; exit; end; end; Result := -1; end; function TMyArray.Length : integer; begin Result := length(TheArray); end; procedure MyFunction; var MyArray : TMyArray; i : integer; begin MyArray.Add(3); MyArray.Add(7); MyArray.Add(10); i := MyArray.IndexOf(10); end; 
+1
source

Source: https://habr.com/ru/post/1265392/


All Articles