加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

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

发布时间:2020-12-15 09:37:05 所属栏目:大数据 来源:网络整理
导读:是否有一个技巧可以将不同类型的记录作为参数传递给过程?例如,看看这个伪代码: type TPerson = record Species: string; CountLegs: Integer; end; TSpider = record Species: string; CountLegs: Integer; Color: TColor; end;var APerson: TPerson; ASpi
是否有一个技巧可以将不同类型的记录作为参数传递给过程?例如,看看这个伪代码:

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);

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读