【问题标题】:Getting type of record field with RTTI fails for static arrays对于静态数组,使用 RTTI 获取记录字段类型失败
【发布时间】:2016-04-17 06:22:24
【问题描述】:

我正在尝试获取记录字段的类型以创建正确的比较器(作为任何/几乎任何记录类型的通用解决方案)。我找不到静态数组的类型信息:

  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 为 nil。 任何想法这里有什么问题? 或者也许有更简单的方法来为要与 TArray/TDictionary 等一起使用的记录创建比较器?

【问题讨论】:

  • 这同样适用于 ShortString 类型(David Heffernan 的解决方案也适用于它们)。

标签: delphi rtti delphi-10-seattle


【解决方案1】:

您需要声明一个类型才能使 RTTI 可用。例如:

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

  TArrFieldTest = record
    a: string;
    b: TMyStaticArrayOfByte;
  end;

【讨论】:

  • 有关动态数组的信息无需声明单独的类型即可获得。如果是静态数组,我们必须声明单独的类型,这是唯一的方法吗?没有我想象的那么好,但总比没有好,谢谢!
  • 动态数组是编译器管理的类型,具有自己的 RTTI,并且包含具有自己的 RTTI 的不同类型的元素,动态数组的 RTTI 链接到该类型的元素。静态数组不是类型,因此没有 RTTI,除非您将其设为类型,否则它只是一块内存。
  • 如果我没记错的话,如果您要使用 RTTI 访问数组的项目,您还必须将范围声明为 MyStaticArrayOfByteRange = 0..3;。
  • @Remy 我的意思是普通动态数组(不是变体),它们对于所有元素(“TArray”或“T 数组”)始终具有相同的类型。你解释了一些内部结构,很好,但我认为“a:array [0..0] of byte”和“a:array of byte”只是声明类型的不同方式。它们都是类型定义,我无法想象为什么 Delphi 只支持其中一个。它限制了为流等编写通用解决方案的能力。托管类型在这里不是边界,支持大多数非托管类型,但不支持静态数组。
  • 小更新:对于托管类型的静态数组(“array[0..1] of string”)可以检索RTTI。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多