【问题标题】:What "type of" declaration represents in Delphi and how can it be usedDelphi 中的“类型”声明代表什么以及如何使用它
【发布时间】:2015-02-17 18:04:55
【问题描述】:

Datasnap.DSReflect单元中有一些奇怪的代码

  TDSAdapterClassType = type of TDSAdapterClass;

  TDSAdapterClass = class(TPersistent)
  private
    FAdapteeInstance: TObject;
  public
    constructor Create(AdapteeInstance: TObject); virtual;
  end;

然后就这样使用

var
  AdapteeInstance: TObject;
  FClassRef: TPersistentClass;

  Result := TDSAdapterClassType(FClassRef).Create(AdapteeInstance);

乍一看,这似乎只是声明类引用的另一种方式。但是逻辑意味着,在不增加更多功能的情况下引入这种语言结构的变体是没有意义的。按照这个逻辑,我发现以下声明可以编译:

type
  TypeOfInteger = type of Integer;
  TypeOfByte = type of Byte;

  TRec = record
    x: integer;
  end;
  TypeOfTRec = type of TRec;

  TBytes = array of byte;
  TypeOfTBytes = type of TBytes;

很有趣,以下声明无法编译。

type
  TypeOfString = type of String;

所以问题是type of 实际代表什么以及如何在实际应用中使用它,除了作为class of 的某种别名

注意: type of 在 Delphi 7 中无法编译,好像后面会介绍,XE 中肯定有,但我没有安装 Delphi 2007-2010在那里试试。

更新:我已经填写了错误报告https://quality.embarcadero.com/browse/RSP-9850

【问题讨论】:

  • 它的行为类似于 type,用于创建不同的类型。
  • @TLama:有趣:我认为(可能是错误的)“TSomethingelse = type TSomething”在 D7 中做到了?
  • TFooClass = type of TFooTFooClass = class of TFoo 相同,但您不能写TIntegerClass = class of Integer,因为Integer 只是一个类型而不是一个类。 TFoo 是一个类类型,因此您可以同时使用这两种类型。 String 因为引用计数而介于类型和接口之间,也许他们错过了包含它或者不知道如何告诉编译器:o)
  • 编译器错误或 Delphi for .NET 的遗留问题,它会给你一个类型引用。 IOW,type TInterfaceRef = type of interface.
  • @David 我确实问过他们,不是吗 ;-) 有些人在这里闲逛。开个玩笑,我确实希望对 QP 报告有一些反馈,但这可能需要一些时间。

标签: delphi


【解决方案1】:

在 Delphi.Net 中,我们在 SysUtils 中有以下定义:

type
  TInterfaceRef = type of interface;

  function Supports(const Instance: TObject; const IID: TInterfaceRef): Boolean; overload; inline;

所以它是class of 的某种替代品,可用于接口类型。

以下文档提到了“类型引用语法(接口类型)”: http://edn.embarcadero.com/article/29780

这里有更多信息: http://hallvards.blogspot.de/2004/11/object-to-interface-casts.html

【讨论】:

  • 所以这是 .NET 遗物。有没有人能够在当前的编译器中利用它做出一些有用的东西,因为我做不到。到目前为止,它仍然属于错误类别。
【解决方案2】:

它似乎与基于 TypeKind 的 PTypeInfo 相关,您可以这样写:

program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TIntType = type of Integer;
  TInt64Type = type of Int64;

var
  intType: TIntType;
  int64Type: TInt64Type;
begin
  try
    intType := Integer;
    Assert(Pointer(intType) = TypeInfo(Integer));
    intType := Cardinal;
    Assert(Pointer(intType) = TypeInfo(Cardinal));
    intType := NativeInt;
    Assert(Pointer(intType) = TypeInfo(NativeInt));
    int64Type := Int64;
    Assert(Pointer(int64Type) = TypeInfo(Int64));
    int64Type := UInt64;
    Assert(Pointer(int64Type) = TypeInfo(UInt64));
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

但它不适用于所有类型,并且会引发一些内部编译器错误。

【讨论】:

  • 我仍然认为这是 .NET 时代的遗留物,它是有意义的。它可能从未在 Windows 和派生的编译器中正确实现。
  • @Rudy 很难理解它的意义
  • 它确实返回了反射数据,IIRC。但那是几年前的事了,所以我可能错了。
  • @Rudy 也许它相当于.net typeof 运算符
【解决方案3】:

没有记录。该行为是不可重复的。有些行为感觉就像class of,但我们不需要其他方法来做到这一点。而 class of 的值类型是无意义的。

我的结论是,这一定是一个编译器错误。该代码无效,应被编译器拒绝。错误是代码被接受而不是被拒绝。

从 Hallvard Vassbotn 的 article 可以看出,type of 是 Delphi .net 编译器的一个功能,它创建映射到 .net 的 System.RuntimeTypeHandle 类型的类型。因此,粗略地说,type of 提供了与 C# typeof 运算符等效的功能。

我最好的猜测是,Delphi 桌面编译器在不应该接受 type of 时接受它,这是 .net 编译器的残余。

【讨论】:

  • 这不是错误,并且已记录在案。查看 Delphi 帮助中的“类型兼容性和标识”一章
  • @Sanders 不,那完全是另一回事
  • 从到目前为止我能收集到的所有信息中,这是正确的答案。 type of 是过去的遗物,无法使用。但是,赏金转到另一个答案,该答案提供了 type of 的来源信息。
猜你喜欢
  • 2013-05-29
  • 1970-01-01
  • 2016-07-13
  • 1970-01-01
  • 2021-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多