delphi – 将不同的记录类型作为参数传递给过程?

是否有一个技巧可以将不同类型的记录作为参数传递给过程?例如,看看这个伪代码

type
  TPerson = record
    Species: string;
    CountLegs: Integer;
  end;

  TSpider = record
    Species: string;
    CountLegs: Integer;
    Color: TColor;
  end;

var
  APerson: TPerson;
  ASpider: TSpider;

// Is there a trick to pass different record types as parameter in a procedure?:
procedure DoSomethingWithARecord(const ARecord: TAbstractRecord?);
begin
  if ARecord is TPerson then
    DoSomethingWithThisPerson(ARecord as TPerson)
  else if ARecord is TSpider then
    DoSomethingWithThisspider(ARecord as TSpider);
end;  

procedure DefineRecords;
begin
  APerson.Species := 'Human';
  APerson.CountLegs := 2;
  ASpider.Species := 'Insect';
  ASpider.CountLegs := 8;
  ASpider.Color := clBtnFace;
  DoSomethingWithARecord(APerson);
  DoSomethingWithARecord(ASpider);
end;

解决方法

记录实例不包含与类相同的类型信息.因此,您需要传递一个额外的参数来指示您正在使用的类型.例如:

type
  Trecordtype = (rtPerson,rtSpider);

procedure DoSomething(recordtype: Trecordtype; const ARecord);
begin
  case recordtype of
  rtPerson:
    DoSomethingWithThisPerson(TPerson(ARecord));
  rtSpider:
    DoSomethingWithThisspider(TSpider(ARecord));
  end;
end;

您可以考虑将类型代码放在每条记录的第一个字段中:

type
  TPerson = record
    recordtype: Trecordtype;
    Species: string;
    CountLegs: Integer;
  end;

  TSpider = record
    recordtype: Trecordtype;
    Species: string;
    CountLegs: Integer;
    Color: TColor;
  end;

function Getrecordtype(ARecord): Trecordtype;
begin
  Result := Trecordtype(ARecord);
end;

....

procedure DoSomething(const ARecord);
begin
  case Getrecordtype(ARecord) of
  rtPerson:
    DoSomethingWithThisPerson(TPerson(ARecord));
  rtSpider:
    DoSomethingWithThisspider(TSpider(ARecord));
  end;
end;

你可以使用泛型:

type
  TMyRecorddispatcher = record
    class procedure DoSomething<T: record>(const Value: T); static;
  end;

class procedure TMyRecorddispatcher.DoSomething<T>(const Value: T); 
begin
  if TypeInfo(T) = TypeInfo(TPerson) then
    DoSomethingWithThisPerson(PPerson(@Value)^)
  else if TypeInfo(T) = TypeInfo(TSpider) then
    DoSomethingWithThisspider(PSpider(@Value)^);
end;

调用这样的函数

TMyRecorddispatcher.DoSomething(APerson);
TMyRecorddispatcher.DoSomething(ASpider);

这使用泛型类型推断,因此您不能显式声明类型.虽然作为泛型的一个例子,它让我感到畏缩.请不要这样做.

在我看来,所有这一切都是凌乱和脆弱的.以上大部分重新实现运行时方法调度,多态.类更适合这个.我不赞同上面的任何代码.

另一方面,也许这一切都是不必要的.有什么不对:

DoSomethingWithThisPerson(Person);
DoSomethingWithThisspider(Spider);

既然您在编译时知道类型,为什么选择更复杂的东西呢?

您可以使用函数重载来省略函数名称中的类型.

procedure DoSomething(const APerson: TPerson); overload;
begin
  ....
end;

procedure DoSomething(const ASpider: TSpider); overload;
begin
  ....
end;

....

DoSomething(Person);
DoSomething(Spider);

相关文章

 从网上看到《Delphi API HOOK完全说明》这篇文章,基本上都...
  从网上看到《Delphi API HOOK完全说明》这篇文章,基本上...
ffmpeg 是一套强大的开源的多媒体库 一般都是用 c/c+&#x...
32位CPU所含有的寄存器有:4个数据寄存器(EAX、EBX、ECX和ED...
1 mov dst, src dst是目的操作数,src是源操作数,指令实现的...