Reputation: 1224
I've been doing some research over records in Delphi, and in most cases I see them used as Type, and then declared a new variable of it, such as:
type
TMyRecord = record
data1: sometype;
data2: sometype;
end;
var
OnesRecord: TMyRecord;
For arrays, it's also used as:
type
TMyRecord = record
data1: sometype;
data2: sometype;
end;
var
OnesRecord: array of TMyRecord;
My questions are the following:
Why one shouldn't use the first approach for arrays, in a way as:
type
TMyRecord = array of record
data1: sometype;
data2: sometype;
end;
var
OnesRecord: TMyRecord;
Also, what would be the difference if one would use records defined directly as variables, such as:
var
OnesRecord: record
data1: sometype;
data2: sometype;
end;
or
var
OnesRecord: array of record
data1: sometype;
data2: sometype;
end;
?
One final thing; if one would merge the second and third approach, and have type of array, and variable of array of that type, would it be any different than having array of array?
So, is this:
type
TMyRecord = array of record
data1: sometype;
data2: sometype;
end;
var
OnesRecord: array of TMyRecord;
any different than this:
type
TMyRecord = record
data1: sometype;
data2: sometype;
end;
var
OnesRecord: array of array of TMyRecord;
Upvotes: 5
Views: 6453
Reputation: 1839
Just to complement the choosen answer, here we go a not so well documented feature for global vars in unit:
Declaration of array of records variables with initialized values
type
TPatch = Packed Record
Pos: NativeUInt;
Old: Byte;
Sup: Byte;
End;
var
OpCodes: Array [1..5] of TPatch = (
(Pos: $044773CF; Old: $7D; Sup: $EB),
(Pos: $04477400; Old: $0D; Sup: $0B),
(Pos: $0447D370; Old: $E3; Sup: $E9),
(Pos: $0447D371; Old: $01; Sup: $99),
(Pos: $0447D372; Old: $13; Sup: $00),
);
Now you can use
Upvotes: 1
Reputation: 7299
Using a Type
declaration lets you easily use it in multiple other types or variables and to pass around variables or constants of that type to procedures and functions.
Type
TCatRecord = Record
Name : string;
Color : string;
End;
TCatArray = Array of TCatRecord;
Var
MyCat : TCatRecord;
NeighbourhoodCats : TCatArray;
...
Procedure SpayACat(aCat: TCatRecord);
Function PickCutestCat(SomeCats: TCatArray): TCatRecord;
...
MyCat := PickCutestCat(NeighbourhoodCats);
Upvotes: 4
Reputation: 613242
It is quite a simple issue. When written like this
type
TPoints = array of record
X, Y: Double;
end;
you are unable to declare variables or parameters that operate on a single element of the array. If you never need to operate on a single item then the above declaration can be reasonable.
Every other aspect of your question is logically the same. Be it arrays of arrays, records containing records, anonymous record and arrays as variable types. The issues and design considerations are just the same.
This question is perhaps a little subjective. In my experience, using an inline or anonymous type as shown above, very often turns out to be a bad choice. Often, at some point of future development, it becomes clear that the anonymous type needs to be named.
So myself, I never use compound types composed from anonymous types. And this way I'm always able to refactor code to use small methods operating on on individual elements. There's never a false constraint pushing me towards large methods operating on the compound type that cannot be decomposed.
So I'd declare that type above as:
type
TPoint = record
X, Y: Double;
end;
TPoints = array of TPoint;
Although in modern Delphi it is much better for type compatibility reasons to omit TPoints
and use TArray<TPoint>
instead.
Upvotes: 5
Reputation: 1838
There's nothing wrong doing what you're doing, just like there's nothing keeping you from overloading the Add() operator to do multiplication.
Your questions are entirely theoretical, and so it's hard to say anything one way or another. Yes, the constructs are "legal". So what?
It's like asking about walking on your hands vs. walking on your feet after you've discovered that you CAN walk on your hands.
The question in all cases is the same ... why would you want to do it?
Rather than asking about coding approaches that are "legal" but nobody uses, why don't you try showing an example where such uses would prove to be an advantage?
From a theoretical standpoint, you're trying to mash-up two different data aggregation mechanisms.
Arrays are a way of collecting items of the same type. Records and classes are a way of collecting related items of different types. They're both containers of sorts, but they have distinct qualities.
You usually declare an array as "array of " not "array of record ... end".
By convention, you define the record as a TYPE so you can "re-use" that type.
You obviously haven't got much experience with this, because you can't actually USE these constructs outside of a very narrow setting.
Let's say you want to define something like "array of integer"; you can define it as a specific type:
type
TIntArray = array of integer;
Why would you do this? Because at times you'll discover that declaring two different things both as "array of integer" makes them not type-compatible, which is counter-intuitive.
But if they're each declared as TIntArray, the compiler accepts that.
I don't know if this is the correct terminology or not, but as far as the compiler is concerned, there IS a difference between "myvar : " and "myvar : ". In this case, would be "TIntArray", and would be "array of integer".
var
myvar1 : array of integer;
myvar2 : TIntArray;
These two are NOT type compatible in all cases. Furthermore,
procedure myproc( AVar : array of integer )
will not accept myproc(myvar2) because myvar2 is not of type "array of integer". Really! It's of type TIntArray. See the difference?
Now replace that declaration with any sort of "record ... end", or even your "array of record ... end" thingie and you start to see the limitations of what you're asking. Yes, the compiler digests it just fine. It just won't let you pass anything in as an argument that matches that type! Even if they "look" exactly the same, believe it or not.
So, to answer your own question, I challenge you to construct a non-trivial example where the things you propose actually make sense and the compiler accepts them. Because while the compiler might accept the isolated examples you've created above, they're not likely to work very well in practice (if at all).
But you get an 'A' for Audacity in asking an insightful question!
Upvotes: 4