Getting type of record field with RTTI fails for static arrays
Asked Answered
F

1

8

I am trying to get types for record fields in order to create correct comparer (as general solution for any/almost any record type). I can't find type information for static arrays:

  TArrFieldTest = record
    a: string;
    b: array[0..3] of byte;
  end;

procedure Test;
var
  rttiContext: TRttiContext;
  rttiType: TRttiType;
  rttiFields: TArray<TRttiField>;
begin
  rttiType := rttiContext.GetType(TypeInfo(TArrFieldTest));
  rttiFields := rttiType.GetFields;
  Assert(rttiFields[0].FieldType<>nil); // it's ok
  Assert(rttiFields[1].FieldType<>nil); // fail here!
end;

FieldType is nil for static array of any type. Any ideas what is wrong here? Or maybe there is easier way to create comparer for records to be used with TArray/TDictionary etc?

Fahey answered 12/1, 2016 at 15:3 Comment(1)
The same applies to ShortString types (and David Heffernan's solution works for them too).Floating
G
12

You need to declare a type in order to have RTTI available. For example:

type
  TMyStaticArrayOfByte = array[0..3] of byte;

  TArrFieldTest = record
    a: string;
    b: TMyStaticArrayOfByte;
  end;
Gnathic answered 12/1, 2016 at 15:11 Comment(6)
Information about dynamic arrays is available without declaration of separate type. In case of static array we have to declare separate type, it is the only way? Not as good as i expected, but better than nothing, thank you!Fahey
A dynamic array is a compiler managed type with its own RTTI, and contains elements of a different type with its own RTTI that the dynamic array's RTTI links to. A static array is not a type, and thus no RTTI, unless you make it a type, otherwise it is just a block of memory.Boldt
If I remember correctly, you also will have to declare the range as MyStaticArrayOfByteRange = 0..3; if you are to access items of the array with RTTI.Gentleness
@Remy I meant normal dynamic array (not variant) , they always have same type for all elements ("TArray<T>" or "Array of T"). You explained some internals, that nice, but i think "a: array[0..0] of byte" and "a: array of byte" just different ways do declare type. Both of them are type definitions, i can't imagine why Delphi support only one of them. It limits ability to code general solutions for streaming etc. Managed type is not a border here, there is support for most of unmanaged types, but not for static arrays.Fahey
Small update: for static array of managed type ("array[0..1] of string") RTTI can be retrieved.Fahey
@AndreiGalatyn: "I meant normal dynamic array (not variant)" - so did I. An explicitly declared type that is a dynamic array has its own RTTI, which contains a reference to the RTTI (if any) of the element type. "i think "a: array[0..0] of byte" and "a: array of byte" just different ways do declare type" - a does not refer to a type in that scenario, it is just a memory block. Byte may have its own RTTI, but a: array[0..0] of Byte and a: array of Byte do not have RTTI for a because a does not refer to a specific type, but TA = array of Byte; a: TA does.Boldt

© 2022 - 2024 — McMap. All rights reserved.