I have the following unit I have used for some Delphi versions. But now I am testing XE8 and I get an error in
function THolydayList.TEnglishNameCollection.ToArray: TArray<string>;
begin
Result := ToArrayImpl(fList.Count);
end;
I think is has to do with the fact that System.Generics.Collections is rewritten in XE8. But pressed for time I haven't had the opportunity to look into that. My question is: has anybody looked into this and can guide me in a direction as of what to look for.
An example of my use of this unit could be the following where I update a table with dates related to an employer for a given year
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;
It's a little frustrating that you say "I get an error" without stating what that error is. Run time error? Compile time error? Please be precise about errors. In my experience, when people don't say what the error is it is often because they didn't read the error message closely and attempt to understand it. That is usually a mistake. So my biggest piece of advice to you is to pay closer attention to such details and hopefully that will help you solve such problems for yourself in the future.
However, since it is clear enough that the call to ToArrayImpl
will fail to compile because ToArrayImpl
is a private member, we can work it out.
Clearly you cannot call ToArrayImpl
because it is private. And the only way we can work out what you need is to read the code in your off site link. Again, not ideal. This code will compile and behave as you intend.
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;
Whether or not this is the best solution to your problem, I am not prepared to say.
Now, one might wonder how your code ever worked. This was due to compiler bugs in older versions. The ToArrayImpl
method has always been private. Older versions of the compiler failed to correctly enforce that visibility and allowed your class to call ToArrayImpl
when it was not meant to.
This code:
uses
Generics.Collections;
type
TMyEnumerable<TObject> = class(TEnumerable<TObject>)
procedure Foo;
end;
procedure TMyEnumerable<TObject>.Foo;
begin
ToArrayImpl(0);
end;
compiles in XE7 but not XE8. Clearly the older compilers were broken.