Tarray构造函数可以中止不添加新记录吗?

时间:2017-12-04 17:51:24

标签: arrays delphi generics delphi-10.1-berlin

我正在尝试控制,限制将多少新记录添加到数组中。这是一个简化的例子:

我正在尝试使用变量LimitToUSA,只允许Country = US的开发人员在数组中创建:

type
  TDevelopers = record
    FName: string;
    LName: string;
    Country: string;
    constructor New(const aFName, aLName, aCountry: string);
  end;

var
  Developers:TArray<TDevelopers>;
  LimitToUSA: boolean; // <-- Controlling variable

constructor TDevelopers.New(const aFName, aLName, aCountry: string);
begin
  if LimitToUSA And (aCountry <> 'US') then
   Exit; // <-- Cancel adding new record here

  FName := aFName;
  LName := aLName;
  Country := aCountry;
end;

procedure TForm2.Button1Click(Sender: TObject);
begin
  LimitToUSA := True;

  Developers := TArray<TDevelopers>.Create(
    TDevelopers.New('John','Smith', 'US'),
    TDevelopers.New('Leo','Hazen', 'CA'),
    TDevelopers.New('Bob','Tilson','UK'),
    TDevelopers.New('Jennifer','Wolken','US'),
    TDevelopers.New('John','Willer','US'));
end;

问题在于它为非美国开发者添加了空记录:

enter image description here

当你有50位开发人员时,这个解决方案很丑陋,维护起来很烦人:

  if LimitToUSA then
  begin
    Developers := TArray<TDevelopers>.Create(
      TDevelopers.New('John','Smith', 'US'),
      TDevelopers.New('Jennifer','Wolken','US'),
      TDevelopers.New('John','Willer','US'));
  end
  else
  begin
    Developers := TArray<TDevelopers>.Create(
      TDevelopers.New('John','Smith', 'US'),
      TDevelopers.New('Leo','Hazen', 'CA'),
      TDevelopers.New('Bob','Tilson','UK'),
      TDevelopers.New('Jennifer','Wolken','US'),
      TDevelopers.New('John','Willer','US'));
  end;

是否有可能以某种方式取消基于构造函数的条件添加新记录?

1 个答案:

答案 0 :(得分:4)

不,你不能这样做。你可以做的是使用TList<TDevelopers>并只添加有效的类实例:

type
  TDevelopers = record
    LName: string;
    FName: string;
    Country: string;
    constructor New(const aFName, aLName, aCountry: string);
  end;

const
  NumDevelopers = 5; // or whatever the real number is.
  ConstDevelopers: array[0..NumDevelopers - 1] of TDevelopers =
  (
    (LName: 'Smith'; FName: 'John'; Country: 'US'),
    (LName: 'Wolken'; FName: 'Jennifer'; Country: 'US'),
    (LName: 'Hazen'; FName: 'Leo'; Country: 'CA'),
    (LName: 'Tilson'; FName: 'Bob'; Country: 'UK'),
    (LName: 'Willer'; FName: 'John'; Country: 'US')
  );

...

var
  Developers: TList<TDevelopers>;
  I: Integer;
begin
  Developers := TList<TDevelopers>.Create;
  for I := 0 to High(ConstDevelopers) do
  begin
    if not LimitToUSA or (ConstDevelopers[I].Country = 'US') then
      Developers.Add(ConstDevelopers[I]);
  end;

现在,如果你真的需要一个数组,你可以使用ToArray。

请注意,我现在无法测试此代码(目前,我只能以安全模式启动此Mac,然后无法使用Windows VM启动Parallels)。 但是它应该给你一些暗示你可以做什么。

替代

或者,您保留代码并删除所有空的记录(检查Country = '')。在最新的Delphi版本(包括 Berlin )中,您可以使用Delete从动态数组中删除字符串Delete。但是要倒退,否则你的索引会遇到麻烦:

for I := High(Developers) downto 0 do
  if Developers[I].Country = '' then
    Delete(Developers, I, 1);

备选方案2

为避免不得不重复,您可以这样做:

  Developers := TArray<TDevelopers>.Create(
    TDevelopers.New('John','Smith', 'US'),
    TDevelopers.New('Jennifer','Wolken','US'),
    TDevelopers.New('John','Willer','US'));
  if not LimitToUSA then
  begin
    ForeignDevelopers := TArray<TDevelopers>.Create(
      TDevelopers.New('Leo','Hazen', 'CA'),
      TDevelopers.New('Bob','Tilson','UK'));
    Developers := Developers + ForeignDevelopers;
  end;