The Delphi RTL contains no classes that implement immutable or read-only lists. You will have to implement such a class yourself, or find a library that offers such functionality.
Make Delphi TList immutable
-
22-06-2023 - |
Pregunta
is it possible to make a Delphi TList immutable?
I searched in the delphi doc for a class similar to the unmodifiableList in java, but didn't found anything.
regards!
Solución 2
Otros consejos
You could use the IReadOnlyList<T>
from Spring4D.
If you have an IList<T>
you just call AsReadOnlyList
(AsReadOnly
since 2.0) and it returns you the same instance as IReadOnlyList<T>
which does not provide methods to manipulate the list (no Add
, Delete
or setter for the Items
property).
However there is a difference to the unmodifiableList
from Java:
In Java you really get a List<T>
which will throw UnsupportedOperationException
when you try to modify it while in Spring4D which is mostly modeled after .NET you get something that you cannot call any modifying operations on.
Here is a simple Generic immutable list implementation with Map & Filter support :
unit Immutable;
interface
uses
System.Generics.Collections;
type
TFilter<TItem> = reference to function(AItem: TItem): Boolean;
TMapper<TItem> = reference to function(AItem: TItem): TItem;
IImmutableList<TItem> = interface
function Insert(Index: Integer; AItem: TItem): IImmutableList<TItem> ;
function Filter(AFilter: TFilter<TItem>): IImmutableList<TItem> ;
function Map(AMapper: TMapper<TItem>): IImmutableList<TItem> ;
function GetEnumerator: TEnumerator<TItem>;
end;
TImmutableList<TItem> = class(TInterfacedObject, IImmutableList<TItem>)
private
FList: TList<TItem>;
public
constructor Create(); overload;
constructor Create(AImmutableList: IImmutableList<TItem>); overload;
destructor Destroy; override;
function Insert(Index: Integer; AItem: TItem): IImmutableList<TItem>;
function Filter(AFilter: TFilter<TItem>): IImmutableList<TItem>;
function Map(AMapper: TMapper<TItem>): IImmutableList<TItem>;
function GetEnumerator: TEnumerator<TItem>;
end;
implementation
{ TImmutableList<TItem> }
constructor TImmutableList<TItem>.Create;
begin
FList := TList<TItem>.Create;
end;
constructor TImmutableList<TItem>.Create(AImmutableList: IImmutableList<TItem>);
var
AItem : TItem;
begin
FList := TList<TItem>.Create;
for AItem in AImmutableList do
FList.Add(AItem);
end;
destructor TImmutableList<TItem>.Destroy;
begin
FList.Free;
inherited;
end;
function TImmutableList<TItem>.GetEnumerator: TEnumerator<TItem>;
begin
Result := FList.GetEnumerator;
end;
function TImmutableList<TItem>.Insert(Index: Integer; AItem: TItem): IImmutableList<TItem>;
var
NewList : TImmutableList<TItem>;
begin
NewList := TImmutableList<TItem>.Create(Self);
TImmutableList<TItem>(NewList).FList.Insert(Index, AItem);
Result := NewList;
end;
function TImmutableList<TItem>.Filter(AFilter: TFilter<TItem>): IImmutableList<TItem>;
var
AItem : TItem;
NewList : TImmutableList<TItem>;
begin
NewList := TImmutableList<TItem>.Create();
for AItem in FList do begin
if AFilter(AItem) then
TImmutableList<TItem>(NewList).FList.Add(AItem)
end;
Result := NewList;
end;
function TImmutableList<TItem>.Map(AMapper: TMapper<TItem>): IImmutableList<TItem>;
var
AItem : TItem;
NewList : TImmutableList<TItem>;
begin
NewList := TImmutableList<TItem>.Create();
for AItem in FList do begin
TImmutableList<TItem>(NewList).FList.Add( AMapper(AItem))
end;
Result := NewList;
end;
end.
I'm using it in https://github.com/pierrejean-coudert/ReduxDelphi TodoMVC sample code.