System.Generics.Collections XE8 与其他 Delphi 版本相比的差异

System.Generics.Collections differences in XE8 compared to other Delphi versions

我有以下用于某些 Delphi 版本的单元。但是现在我正在测试 XE8 并且在

中出现错误
function THolydayList.TEnglishNameCollection.ToArray: TArray<string>;
begin
  Result := ToArrayImpl(fList.Count);
end;

我认为这与 System.Generics.Collections 在 XE8 中被重写有关。但是时间紧迫,我还没有机会去研究那个。 我的问题是:有没有人调查过这个并且可以指导我寻找什么的方向。

我使用这个单位的一个例子如下,我用给定年份

与雇主相关的日期更新 table
procedure TsCalendarYearHolyday(aEmployer: string; aYear: integer);
var
  STDDato: TStdDato;
  HolyDay : THolyDay;
  Query: TUniQuery;
begin
  Query := frmUniConn.CreateQuery;
  STDDato := TStdDato.Create;
  STDDato.Year := aYear;
  STDDato.Country := Denmark;
  STDDato.MarkSunday := False;
  STDDato.Language := hdNative;
  STDDato.MakeHoliDays(0);
  try
    Query.SQL.Clear;
    Query.SQL.Add('UPDATE ' + TableTsCalendarYear);
    Query.SQL.Add('   SET flddayspecial = :flddayspecial');
    Query.SQL.Add('      ,flddaydesc = :flddaydesc');
    Query.SQL.Add('      ,flddaynormal = :flddaynormal');
    Query.SQL.Add(' WHERE (flddate = :flddate)');
    Query.SQL.Add('   AND (fldemployer = :fldemployer)');
    for HolyDay in STDDato.Liste do
      begin
        try
          Query.ParamByName('flddayspecial').AsBoolean := True;
          Query.ParamByName('flddaydesc').AsString := Holyday.NativeName;
          Query.ParamByName('flddaynormal').AsFloat := 0;
          Query.ParamByName('flddate').AsDate := HolyDay.Date;
          Query.ParamByName('fldemployer').AsString := aEmployer;
          Query.Execute;
        except
          on E: exception do
            Logfile.Error('U_TsCalendars.TsCalendarYearHolyday: ' + E.Message);
        end;
      end;
  finally
    FreeAndNil(STDDato);
    Query.Free;
  end;
end;

I added a link since this is the whole unit

您说 "I get an error" 而没有说明错误是什么,这有点令人沮丧。 运行时间错误?编译时错误?请准确指出错误。根据我的经验,当人们不说出错误是什么时,通常是因为他们没有仔细阅读错误消息并试图理解它。这通常是一个错误。所以我给你最大的建议就是多注意这些细节,希望这能帮助你将来自己解决这些问题。


但是,由于 ToArrayImpl 是私有成员,所以很明显调用 ToArrayImpl 将无法编译,我们可以解决这个问题。

显然你不能调用 ToArrayImpl 因为它是私有的。我们可以计算出您需要的唯一方法是阅读您场外的代码 link。再次,不理想。此代码将按您的预期进行编译和运行。

function THolydayList.TEnglishNameCollection.ToArray: TArray<string>;
var
  i: Integer;
begin
  SetLength(Result, fList.Count);
  for i := 0 to fList.Count-1 do
    Result[i] := fList[i].EnglishName;
end;

这是否是您问题的最佳解决方案,我不准备说。


现在,您可能想知道您的代码是如何工作的。这是由于旧版本中的编译器错误。 ToArrayImpl 方法一直是私有的。旧版本的编译器无法正确执行该可见性,并允许您的 class 在本不该调用的情况下调用 ToArrayImpl

此代码:

uses
  Generics.Collections;

type
  TMyEnumerable<TObject> = class(TEnumerable<TObject>)
    procedure Foo;
  end;

procedure TMyEnumerable<TObject>.Foo;
begin
  ToArrayImpl(0);
end;

在 XE7 中编译,但在 XE8 中不编译。显然旧的编译器坏了。