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

时间:2015-08-05 08:42:21

标签: delphi delphi-xe8 generic-collections

我有一些用于Delphi版本的单元。但现在我正在测试XE8,我在

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

我认为这与在XE8中重写System.Generics.Collections的事实有关。但是时间紧迫,我没有机会调查这一点。 我的问题是:有没有人研究过这个问题,可以引导我朝着寻找目标的方向前进。

我使用这个单位的一个例子可能是以下我更新表格,其中包含与给定年份的雇主相关的日期

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

1 个答案:

答案 0 :(得分:3)

你说“我得到一个错误”并没有说明错误是什么,这有点令人沮丧。运行时错误?编译时间错误?请准确说明错误。根据我的经验,当人们没有说出错误是什么时,通常是因为他们没有仔细阅读错误消息并试图理解它。这通常是一个错误。因此,我给你的最大建议就是密切关注这些细节,希望这将有助于你在将来为自己解决这些问题。

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

显然,您无法拨打ToArrayImpl,因为它是私密的。我们能够找到您需要的唯一方法是阅读您的非现场链接中的代码。再次,不理想。此代码将按照您的意图编译和运行。

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方法一直是私有的。较旧版本的编译器无法正确强制执行该可见性,并允许您的类在不需要时调用ToArrayImpl

此代码:

uses
  Generics.Collections;

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

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

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