Leaderboard
Popular Content
Showing content with the highest reputation on 04/22/25 in all areas
-
Hi everyone, I wanted to share some practical benchmark results from testing Delphi 12.3 under Parallels Desktop (Windows 11 ARM) on my new Mac Studio M4 Max. I'm working on a large ERP project (around 1 million lines of code) using components from Fast Report, TMS Software, and DevExpress. Here’s a direct comparison between three systems I’ve tested: Build config Intel i5-12500 (Win11, 32 GB) Mac Mini M4 Pro (24 GB) Mac Studio M4 Max (36 GB) --------------------------------------------------------------------------------------------------------------- Win64 Clean + Build 32 sec 26 sec 24 sec Win64 Clean + Compile 21 sec 18 sec 17 sec Win32 Clean + Build 23 sec 19 sec 17 sec Win32 Clean + Compile 16 sec 14 sec 13 sec All tests were run in Parallels Desktop 20, with each Mac VM configured optimally (RAM and CPU cores adjusted per machine). The Intel system was running native Windows 11 Pro with 32 GB RAM. Windows 11 ARM inside Parallels ran Delphi 12.3 without any issues. Key impressions: Mac Studio M4 Max delivers excellent performance even under virtualization. Parallels Desktop is extremely stable — no issues with Firebird or IBExpert either. For large Delphi projects, it’s a very viable setup for professional development. Best regards, Bojan
-
Letting AI Handle the Docs: Experiments with Doxygen Comment Blocks
Dalija Prasnikar replied to mjustin's topic in Tips / Blogs / Tutorials / Videos
Few notes. First, when using free AI variants, your code will end up in the AI training data. And I wouldn't trust paid versions either. You need to be very careful that you don't give AI access to sensitive code that contains data which should not end up there. It is also very easy to do that by accident and it is prudent to run AI interactions in restricted environment like VM where you will have only non sensitive code. Next, anything that AI gives out needs to be carefully reviewed by human. AI often hallucinates and sometimes those hallucinations are not as obvious. This is especially important for code which requires some detailed explanations about how it works and why or some reasoning only person who wrote the code can answer (or the reasons are written in some other documents like specifications or design). Similar goes to writing tests with AI help. One of the huge problems with AI usage, is that with time, reviewing its output becomes a mundane task and this is where mistakes can more easily creep in. -
There is an iOS simulator via XCode available on the Mac you'll need to package and sign the app anyway. But if you don't want to buy a Mac (Minis are quite cheap though), you can rent a Mac online via services like MacInCloud, MacStadium or OakHost just to name a few.
-
First of all, look at the first column, this list was done in less than a second.
-
msmpeng is Windows defender. Try to temporarily disable it and see whether the performance improves.
-
You're absolutely right — thanks for catching that. Just to clarify: I’m actually running Parallels Desktop 20, not 19. Apologies for the incorrect info, and thank you for pointing it out.
-
Now we are discussing what the cheap and rubbish version of ChatGPT says about Delphi?
-
Check that the network card isn't powering down to save electricity. Windows is starting to set that stuff on it's own after updates. It now "shuts down" the monitor to save power after the screen saver is on after a few minutes, and there's no way to change that on, but a network card put to sleep can be overridden
-
Letting AI Handle the Docs: Experiments with Doxygen Comment Blocks
dummzeuch replied to mjustin's topic in Tips / Blogs / Tutorials / Videos
But we have Vibe Coding now! -
No, I don't see the point -- there are already so many people who actually do hardware comparisons for a living writing about it. Aside from commenting here in the context of a Delphi developer, I don't have time to write my experience in detail. I will just add this: I bought a Snapdragon Windows PC when I saw that users of my software were installing it on Snapdragon Windows PCs, but that the 32-bit version of my software was appearing instead of the 64-bit. I quickly realized this was due to how the Inno Setup script was written, which assumed that if x64 was not available that the system needed the 32-bit x86 binaries installed. Inno added support for some additional scripting functions to better handle this and I wanted to test my software on Snapdragon so I bought one and fixed the install script. That works perfectly. And now any time I need to grab a portable PC I take the Snapdragon one because its the lightest Windows PC I have and the one with the best battery life. I've had no issues doing what I need to do on it. This is not some cheesy WinRT netbook from 12 years ago that can only open a web browser and play Candy Crush and run Office apps. This is the Windows answer to an Apple MacBook (which I have two of also).
-
When 100% of Delphi developers were Windows users who just wanted a button they could push to cross-compile their code to Linux, they gave us a new framework and attempted to get the IDE itself to run on Linux. Linux desktop was barely even a thing then. In the modern era, when nothing cool starts on Windows anymore and according to Stack Overflow's survey less than 50% of developers develop on a Windows box, they give us a cross compiler and a Windows-only IDE. Delphi wasn't burned... it set itself on fire, repeatedly. It's no different from their decision that you have to pay $4,000 to target a free operating system.
-
Forward-looking statements relate to investors and profitability projections and have nothing to do with software feature roadmaps. More importantly, Idera is a privately-held company so no law about forward-looking statements would apply to them! They don't make roadmaps because in the early days they were notoriously late with everything (long before Idera bought them). They took polls to decide on the top five most-desired features and then shipped a version of Delphi that included none of them. Other things slipped past deadlines and users rightly called them out on this. That's when the road maps dried up. They just didn't want to be embarrassed anymore when they failed to deliver on time.
-
For Delphi / RAD Studio version 12.3, the original solution provided by Jim: C:\> getitcmd -i=fmxlinux-12-1.78 works "out of the box" with no issues !! ( --> no "patch" needed as in 12.2 ) You can use this solution to get "FMX Linux" until they reach a final agreement with Kryukov's state ...
-
As you likely noticed, Delphi 11 officially does not support Windows XP anymore. You can make your application compatible with XP again by simple set. In Project Options|Building|Delphi Compiler|Linking set "Set OS Version fields in PE Headers" and "Set SubSystem Version fields in PE Headers" to "5.1". Unless your application uses System.Threading.pas (TTask etc) you should run it under Windows XP with no problems. But if so, then you have to tweak this unit. Threading objects actually use in their internals new TThread.GetTickCount64 method, which is hardwired to Windows API GetTickCount64 which is not available in Windows XP API. Take this unit from "source\rtl\common" folder in Delphi 11 installation. Declare new local function in the beginning of implementation section of this unit like this: function _GetTickCount64: UInt64; begin if TOSVersion.Major<6 then Result := TThread.GetTickCount else Result := TThread.GetTickCount64; end; and replace all occurrences of TThread.GetTickCount64 calls with _GetTickCount64. For Win32 applications then copy this modified unit to \lib\win32\debug and \lib\win32\release folders in Delphi 11 installation and rename original System.Threading.dcu to e.g. _System.Threading.dcu. Then build your project which uses System.Threading with Debug and Release configuration. New System.Threading.dcu should be created in mentioned folders. After this you should remove modified System.Threading.pas from these folders to prevent its recurrent compilation. Now your Delphi 11 Win32 applications should run under Windows XP with no External Exception crash.
-
From my code base I find this: TThreadsafe<T> = class private FLock: TCriticalSection; FValue: T; function GetValue: T; procedure SetValue(const NewValue: T); public constructor Create; destructor Destroy; override; property Value: T read GetValue write SetValue; end; And this: Enum<T: record> = class strict private class function TypeInfo: PTypeInfo; static; class function TypeData: PTypeData; static; public class function IsEnum: Boolean; static; class function Count: Integer; static; class function ToOrdinal(Value: T): Integer; static; class function FromOrdinal(Value: Integer): T; static; class function TryFromOrdinal(Value: Integer; out Enum: T): Boolean; static; class function ToString(Value: T): string; static; class function FromString(const Value: string): T; static; class function MinValue: Integer; static; class function MaxValue: Integer; static; class function InRange(Value: Integer): Boolean; static; class function EnsureRange(Value: Integer): Integer; static; class function FromName(const Name: string): T; static; class function TryFromName(const Name: string; out Enum: T): Boolean; static; class function ToName(Item: T): string; static; class function ToNewSentenceName(Item: T): string; static; class function ToMidSentenceName(Item: T): string; static; class function ToUpperCaseName(Item: T): string; static; class function ToPascalCaseName(Item: T): string; static; end; And this: TArray = class public type TWriteItem<T> = reference to procedure(const TaggedFile: ITaggedFile; const Item: T); TReadItem<T> = reference to procedure(const TaggedFile: ITaggedFile; out Item: T); strict private const SortOrderFactor: array [TSortOrder] of Integer = (1, -1); public class procedure Swap<T>(var Left, Right: T); static; class procedure Reverse<T>(var Values: array of T; Index, Count: Integer); overload; static; class procedure Reverse<T>(var Values: array of T); overload; static; class function Reversed<T>(const Values: array of T): TArray<T>; static; class procedure Shuffle<T>(var Values: array of T; const Random: TFunc<Integer, Integer>; Index, Count: Integer); overload; static; class procedure Shuffle<T>(var Values: array of T; const Random: TFunc<Integer, Integer>); overload; static; class function Contains<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index, Count: Integer; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index, Count: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>; Index, Count: Integer; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>; Index, Count: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; Index, Count: Integer; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; out ItemIndex: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T; Index, Count: Integer): Boolean; overload; static; class function Contains<T>(const Values: array of T; const Item: T): Boolean; overload; static; class function Matches<T>(const Values: array of T; const Predicate: TPredicate<T>; out ItemIndex: Integer): Boolean; overload; static; class function Matches<T>(const Values: array of T; const Predicate: TPredicate<T>): Boolean; overload; static; class function Matches<T>(const Values: array of T; const Predicate: TPredicateOfObj<T>; out ItemIndex: Integer): Boolean; overload; static; class function Matches<T>(const Values: array of T; const Predicate: TPredicateOfObj<T>): Boolean; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>; Index, Count: Integer): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; const Comparer: IEqualityComparer<T>): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>; Index, Count: Integer): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; EqualOp: TEqualOp<T>): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T; Index, Count: Integer): Integer; overload; static; class function IndexOf<T>(const Values: array of T; const Item: T): Integer; overload; static; class function Equal<T>(const lhs, rhs: array of T; const Comparer: IEqualityComparer<T>): Boolean; overload; static; class function Equal<T>(const lhs, rhs: array of T; EqualOp: TEqualOp<T>): Boolean; overload; static; class function Equal<T>(const lhs, rhs: array of T): Boolean; overload; static; class function Ordered<T>(const Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer): Boolean; overload; static; class function Ordered<T>(const Values: array of T; const Comparer: IComparer<T>): Boolean; overload; static; class function Ordered<T>(const Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer): Boolean; overload; static; class function Ordered<T>(const Values: array of T; const Comparison: TComparison<T>): Boolean; overload; static; class function Ordered<T>(const Values: array of T; Index, Count: Integer): Boolean; overload; static; class function Ordered<T>(const Values: array of T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparer: IEqualityComparer<T>; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparer: IEqualityComparer<T>; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; EqualOp: TEqualOp<T>; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; EqualOp: TEqualOp<T>; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparer: IComparer<T>; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparer: IComparer<T>; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparison: TComparison<T>; out Value: T; Index, Count: Integer): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparison: TComparison<T>; out Value: T): Boolean; overload; static; class function HasDuplicates<T>(const Values: array of T; const Comparison: TComparison<T>): Boolean; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IEqualityComparer<T>; Index, Count: Integer; const Dispose: TProcOfObj<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IEqualityComparer<T>; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IEqualityComparer<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; EqualOp: TEqualOp<T>; Index, Count: Integer; const Dispose: TProcOfObj<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; EqualOp: TEqualOp<T>; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; EqualOp: TEqualOp<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer; const Dispose: TProcOfObj<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparer: IComparer<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; const Comparison: TComparison<T>): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T; Index, Count: Integer): Integer; overload; static; class function RemoveDuplicates<T>(var Values: array of T): Integer; overload; static; class function Sorted<T>(const Values: array of T; const Comparer: IComparer<T>; Order: TSortOrder; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparer: IComparer<T>; Order: TSortOrder): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparer: IComparer<T>): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparison: TComparison<T>; Order: TSortOrder; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparison: TComparison<T>; Order: TSortOrder): Boolean; overload; static; class function Sorted<T>(const Values: array of T; const Comparison: TComparison<T>): Boolean; overload; static; class function Sorted<T>(const Values: array of T; Order: TSortOrder; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; Index, Count: Integer): Boolean; overload; static; class function Sorted<T>(const Values: array of T; Order: TSortOrder): Boolean; overload; static; class function Sorted<T>(const Values: array of T): Boolean; overload; static; class procedure Sort<T>(var Values: array of T; const Comparer: IComparer<T>; Order: TSortOrder; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; const Comparer: IComparer<T>; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; const Comparer: IComparer<T>; Order: TSortOrder); overload; static; class procedure Sort<T>(var Values: array of T; const Comparer: IComparer<T>); overload; static; class procedure Sort<T>(var Values: array of T; const Comparison: TComparison<T>; Order: TSortOrder; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; const Comparison: TComparison<T>; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; const Comparison: TComparison<T>; Order: TSortOrder); overload; static; class procedure Sort<T>(var Values: array of T; const Comparison: TComparison<T>); overload; static; class procedure Sort<T>(var Values: array of T; Order: TSortOrder; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; Index, Count: Integer); overload; static; class procedure Sort<T>(var Values: array of T; Order: TSortOrder); overload; static; class procedure Sort<T>(var Values: array of T); overload; static; class function Copy<T>(const Source: array of T; Index, Count: Integer): TArray<T>; overload; static; class function Copy<T>(const Source: array of T): TArray<T>; overload; static; class procedure Move<T>(const Source: array of T; var Dest: array of T; Index, Count: Integer); overload; static; class procedure Move<T>(const Source: array of T; var Dest: array of T); overload; static; class function Concatenated<T>(const Source1, Source2: array of T): TArray<T>; overload; static; class function Concatenated<T>(const Source: array of TArray<T>): TArray<T>; overload; static; class procedure Initialise<T>(var Values: array of T; const Value: T); static; class function New<T>(Count: Integer; const Value: T): TArray<T>; static; class function Zero<T>(Count: Integer): TArray<T>; static; class procedure Zeroise<T>(var Values: array of T); static; class procedure Free<T: class>(const Values: array of T); static; class procedure FreeAndNil<T: class>(var Values: array of T); static; class function GetHashCode<T>(const Values: array of T; const Comparer: IEqualityComparer<T>): Integer; overload; static; class function GetHashCode<T>(const Values: array of T): Integer; overload; static; class function GetHashCode<T>(Values: Pointer; Count: Integer; const Comparer: IEqualityComparer<T>): Integer; overload; static; class function GetHashCode<T>(Values: Pointer; Count: Integer): Integer; overload; static; class procedure Write<T>(const TaggedFile: ITaggedFile; const WriteItem: TWriteItem<T>; const Values: TArray<T>); overload; static; class procedure Write<T>(const TaggedFile: ITaggedFile; const Values: TArray<T>); overload; static; class procedure Read<T>(const TaggedFile: ITaggedFile; const ReadItem: TReadItem<T>; out Values: TArray<T>); overload; static; class procedure Read<T>(const TaggedFile: ITaggedFile; out Values: TArray<T>); overload; static; class procedure Skip(const TaggedFile: ITaggedFile); static; end; And this: NDArray<T> = record public type {$POINTERMATH ON} P = ^T; {$POINTERMATH OFF} private type TEnumerator = record private FOwner: ^NDArray<T>; FCurrentIndices: TArray<Integer>; function GetCurrent: T; public class function New(const Owner: NDArray<T>): TEnumerator; static; property Current: T read GetCurrent; function MoveNext: Boolean; end; private FBase: P; FValues: TArray<T>; FRank: Integer; FShape: TArray<Integer>; FStride: TArray<NativeInt>; function LinearIndex(const Indices: array of Integer): NativeInt; function GetCount: NativeInt; function GetItem(const Indices: array of Integer): T; procedure SetItem(const Indices: array of Integer; const Value: T); function GetSlice(const Indices: array of Integer): NDArray<T>; procedure SetSlice(const Indices: array of Integer; const Value: NDArray<T>); function GetIsEmpty: Boolean; function GetHasZeroDimension: Boolean; public class function New(const Shape: array of Integer): NDArray<T>; overload; static; class function New(const Shape: array of Integer; const Values: TArray<T>): NDArray<T>; overload; static; class function New(const Shape: array of Integer; const Value: T): NDArray<T>; overload; static; class function Zero(const Shape: array of Integer): NDArray<T>; static; class function Diagonal(const Values: array of T): NDArray<T>; overload; static; class function Diagonal(Size: Integer; const Value: T): NDArray<T>; overload; static; class function Empty: NDArray<T>; static; class operator Explicit(const arr: TArray<T>): NDArray<T>; property IsEmpty: Boolean read GetIsEmpty; property HasZeroDimension: Boolean read GetHasZeroDimension; property Rank: Integer read FRank; property Shape: TArray<Integer> read FShape; property Stride: TArray<NativeInt> read FStride; property Count: NativeInt read GetCount; property DataPtr: P read FBase; property Items[const Indices: array of Integer]: T read GetItem write SetItem; default; function ItemPtr(const Indices: array of Integer): P; property Slice[const Indices: array of Integer]: NDArray<T> read GetSlice write SetSlice; procedure CopyTo(Dest: P; Count: NativeInt); function Clone: NDArray<T>; function ToFlattenedArray: TArray<T>; class procedure Write(const TaggedFile: ITaggedFile; const WriteItem: TArray.TWriteItem<T>; const Value: NDArray<T>); overload; static; class procedure Write(const TaggedFile: ITaggedFile; const Value: NDArray<T>); overload; static; class procedure Read(const TaggedFile: ITaggedFile; const ReadItem: TArray.TReadItem<T>; out Value: NDArray<T>); overload; static; class procedure Read(const TaggedFile: ITaggedFile; out Value: NDArray<T>); overload; static; public function GetEnumerator: TEnumerator; end; And this: TIterativeSolver<T> = class public type P = ^T; protected class procedure AGSIterate(A, b, x, work: P; N: Integer; Storage: TMatrixStorage); static; class procedure AGSCalcResidual(A, b, x, r: P; N: Integer; Storage: TMatrixStorage); static; class function AGSIsZero(b: P; N: Integer): Boolean; static; class function AGSSqrMag(x: P; N: Integer): Double; static; class function AGSAccel(r, x: P; work: Pointer; iter, N: Integer): Boolean; static; public class function SolveAGS(const A: NDArray<T>; var b: NDArray<T>; maxiter: Integer; tol: Double; out iter: Integer): Boolean; static; end; And this: type TLUSolver<T> = class public type P = ^T; TWorkspace = record public ipiv: TArray<Integer>; public procedure Update(N: Integer); end; protected //protected to avoid spurious compiler warning class procedure DecomposeDense(A: P; ipiv: PInteger; N: Integer); overload; static; class procedure SubstituteDense(A: P; ipiv: PInteger; N: Integer; b: P; Storage: TMatrixStorage); static; class procedure DecomposeBanded(A: P; ipiv: PInteger; N, Bandwidth, ldab: Integer); overload; static; class procedure SubstituteBanded(A: P; ipiv: PInteger; N, Bandwidth, ldab: Integer; b: P; Storage: TMatrixStorage); static; class procedure DecomposeDense(A: P; N: Integer; var Workspace: TWorkspace); overload; static; class procedure DecomposeBanded(A: P; N, Bandwidth, ldab: Integer; var Workspace: TWorkspace); overload; static; public class procedure Decompose(var A: NDArray<T>; var Workspace: TWorkspace); static; class procedure Substitute(var A, b: NDArray<T>; const Workspace: TWorkspace); static; class procedure Solve(var A, b: NDArray<T>); static; end; And this: TData<T> = record x: T; xPrime: TArray<T>; xPrimePrime: TArray<TArray<T>>; xPrimePrimePrime: TArray<TArray<TArray<T>>>; end; And this: TTableItem<T: TModelObject> = record public ModelObject: T; ObjectIndex: Integer; ItemIndex: Integer; public class function New(ModelObject: T; ObjectIndex, ItemIndex: Integer): TTableItem<T>; static; class function DisplayName(ModelObject: TModelObject; const ItemName: string; ItemIndex: Integer): string; overload; static; function DisplayName(const ItemName: string): string; overload; procedure RedirectDataAccess(var Handler: TDataObject; var Index: Integer); end; I could go on, but it's pretty boring. And these are just some examples from one particular code base. Other code bases will have different use cases. As Stefan said, generics are used for generic programming. So yeah, a myriad.
-
RTTI info for TBytes using runtime packages
Stefan Glienke replied to Wagner Landgraf's topic in RTL and Delphi Object Pascal
The issue is that TBytes is an alias for TArray<Byte> - generic types being used across different modules have several implications such as that they manifest into each module with their own typeinfo being generated. Try this code for example: uses Rtti, SysUtils; var ctx: TRttiContext; begin Writeln(ctx.GetType(TypeInfo(TBytes)).QualifiedName); end. In a regular console application it will print: System.TArray<System.Byte> While you would assume that it should print: System.SysUtils.TBytes Now if you enable runtime packages for this console application and let it link with rtl you will get an ENonPublicType here. Every module that is using TBytes is not referencing some type that is declared in the RTL runtime package but emiting its own version of TArray<Byte> into its binary. Personally I think this is an issue with the compiler treating the declaration of TBytes = TArray<Byte> different from TBytes = array of Byte in terms of the typeinfo generated - I was sure there is a QP entry somewhere about it but I cannot find it right now. To further provide the proof that aforementioned assumptions of other posters are wrong use the following code with a console application linking with the rtl package: uses Rtti, TypInfo, Classes, SysUtils; var ctx: TRttiContext; begin Writeln(ctx.GetType(TBytesStream).GetField('FBytes').FieldType.Handle = TypeInfo(TBytes)); end. This will print FALSE as the typeinfo of the FBytes field which is of type System.SysUtils.TBytes in fact differs from the typeinfo generated for the usage of TBytes in the console application binary. In fact there does not even exist a type called TBytes but only System.TArray<System.Byte> as TBytes it just an alias as I said and the declaration TBytes = type TArray<Byte> is not legit and raises E2574 Instantiated type can not be used for TYPE'd type declaration