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!

¿Fue útil?

Solución 2

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.

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.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top