Defining Records in Delphi - (Record as Type vs Record as Variable) - Differences, Cons and Pros?

I'm researching records in Delphi and most of the time I see them being used as a Type and then declaring a new variable like:

type
  TMyRecord = record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: TMyRecord;

      

For arrays, it is also used like:

type
  TMyRecord = record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: array of TMyRecord;

      

My questions are:

Why can't you use the first approach for arrays, because:

type
  TMyRecord = array of record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: TMyRecord;

      

Also, what's the difference if you 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 last thing; if someone combined the second and third approaches and had an array type and an array variable of that type, would it be anything other than having an array of an array?

So here's what:

type
  TMyRecord = array of record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: array of TMyRecord;

      

different from this:

type
  TMyRecord = record
    data1: sometype;
    data2: sometype;
  end;

var
  OnesRecord: array of array of TMyRecord;

      

+3


source to share


4 answers


There is nothing wrong with what you do, just as there is nothing to stop you from overloading the Add () operator for multiplication.

Your questions are completely theoretical and therefore it is difficult to say anything anyway. Yes, the designs are "legal". So what?

He likes to ask about walking on your hands or walking on your legs when you've found that you can walk on your hands.

The question is the same in all cases ... why do you want to do this?

Rather than asking about coding approaches that are "legal" but not used by anyone, why not try to show an example of when such use is useful?

From a theoretical point of view, you are trying to put together two different data aggregation mechanisms.

Arrays are a way to collect items of the same type. Records and Classes are a way of collecting related items of different types. They are both containers, but they have excellent qualities.

Usually you declare an array as "array" rather than "array of record ... end".

By convention, you define a record as a TYPE so that you can "reuse" that type.

You obviously don't have much experience with this because you cannot use these constructs outside of a very narrow setting.

Suppose 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 from time to time you find that declaring two different things as an "array of an integer" makes them incompatible with the type, which is counter intuitive.

But if they are 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, it will be "TIntArray" and will be an "array of integers".

var
  myvar1 : array of integer;
  myvar2 : TIntArray;

      

These two types are NOT compatible in all cases. Besides,

procedure myproc( AVar : array of integer )

      

will not accept myproc (myvar2) because myvar2 is not of type "array of integers". Indeed! This is the TIntArray type. See Difference?

Now replace that declaration with any "record ... end" type, or even your "record ... end" thingie, and you will start to see the limitations of what you are asking for. Yes, the compiler understands very well. It just won't let you pass anything 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 encourage you to build a non-trivial example where the things you suggest actually make sense and the compiler accepts them. Because while the compiler may accept the isolated examples you created above, they are unlikely to work very well in practice (if at all).

But you get an "A" for Audacity by asking an insightful question!

+4


source


This is a fairly simple problem. When is it written

type
  TPoints = array of record
    X, Y: Double;
  end;

      

you cannot declare variables or parameters that operate on a single element of an array. If you never need to work with a single element, the above expression might make sense.

All other aspects of your question are logically the same. Be it arrays of arrays, records containing records, anonymous notation, and arrays as variable types. The design questions and considerations are the same.




This question is perhaps a bit subjective. In my experience, using an inline or anonymous type as shown above is very often a bad choice. It often becomes clear at some point in future development that an anonymous type should be named.

So, I never use complex types made up of anonymous types. And this way I can always refactor the code to use small methods that work on individual elements. There never a false constraint pushes me towards big methods acting on a complex type that cannot be decomposed.

So I declare this type above:

type
  TPoint = record
    X, Y: Double;
  end;
  TPoints = array of TPoint;

      

Although in modern Delphi it is much better for type compatibility reasons to skip TPoints

and use TArray<TPoint>

.

+5


source


Using a declaration Type

allows you to easily use it in several other types or variables and pass 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); 

      

+4


source


To complement the selected answer, here we are not documenting the function for global vars in a block as well:

Declaring an array of variable records 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

0


source







All Articles