Reputation: 6015
I want to do this in XE5:
type
TMyRec = record
// fields
class function GetList: TMyRecArr; static;
end;
TMyRecArr = array of TMyRec;
I've already seen "Forward declarations for record types" and "how to do a typed forward declaration?", but they seem irrelevant since my problem is not passing the record as a parameter.
Upvotes: 12
Views: 12239
Reputation: 4164
Instead of trying to add forward decalrations to records (which up until now still isn't possible in Delphi), there is a way around this : move functions that reference another record type towards a record helper, declared where both record types are in scope.
type
RecordA = record
// [...]
end;
RecordB = record
// [...]
end;
RecordAHelper = record helper for RecordA
procedure Call(argument: RecordB);
end;
After obvioulsy implementing this, above allows one to write (and compile and run) : RecordA_variable.Call(RecordB_variable)
Upvotes: 0
Reputation: 6015
Well, I searched a little more, and found that I can use helpers to do this:
type
TMyRec = record
// fields
end;
TMyRecArr = array of TMyRec;
TMyRecHelper = record helper for TMyRec
class function GetList: TMyRecArr; static;
end;
Sure it lacks benefits of generics that David mentioned in his answer and comments, but it doesn't make the code auto-complete unusable! I mean one may comes to this conclusion that the flexibility that TArray<T>
offers is not needed in some piece of code. Then it would be nothing more than increment in memory usage of the final running application or possibly lower performance.
Upvotes: 0
Reputation: 4878
Since declarations of pointers types are permitted before the type definition, slightly modifying your function you're allowed to do this:
type
PMyRecArr = ^TMyRecArr;
TMyRec = record
// fields
class procedure GetList(const arr: PMyRecArr); static;
end;
TMyRecArr = array of TMyRec;
The procedure implementation and its usage follow:
class procedure TMyRec.GetList(const arr: PMyRecArr);
begin
SetLength(arr^, 4);
end;
var
arr: TMyRecArr;
begin
TMyRec.GetList(@arr);
Writeln(Length(arr));//prints 4
end.
Upvotes: 1
Reputation: 613252
You cannot use a forward declaration to declare a record type or an array type. But not to fear. You can use a generic dynamic array, TArray<T>
.
type
TMyRec = record
class function GetList: TArray<TMyRec>; static;
end;
This is actually better than declaring TMyRecArr
as per the code in your question. That's because the generic TArray<T>
has more flexible type identity than a traditional dynamic array type. You can use TArray<T>
with generic types defined in libraries that are independent and unaware of your code.
Now, you could declare the type like this:
type
TMyRec = record
type TMyRecArray = array of TMyRec;
class function GetList: TMyRecArray; static;
end;
And then your array type is TMyRec.TMyRecArray
. But I urge you not to do this. You'll have a type that can only be used with you code, and cannot be used with third party code.
In summary, TArray<T>
is your friend.
Upvotes: 19