使Delphi TList不可变

时间:2014-03-27 16:08:20

标签: delphi immutability delphi-xe4 tlist

是否可以使Delphi TList不可变?
我在delphi doc中搜索了一个类似于java中unmodifiableList的类,但没有找到任何东西。

问候!

3 个答案:

答案 0 :(得分:4)

您可以使用Spring4D的IReadOnlyList<T>

如果您有IList<T>,则只需拨打AsReadOnlyList即可返回与IReadOnlyList<T>相同的实例,该实例不提供操作列表的方法(无AddDelete属性的Items或setter。

然而,Java中的unmodifiableList存在差异:

在Java中,你真的得到一个List<T>当你尝试修改它时会抛出UnsupportedOperationException,而在Spring4D中,它主要是在.NET之后建模的,你会得到一些你不能调用任何修改操作的东西。

答案 1 :(得分:2)

Delphi RTL不包含实现不可变列表或只读列表的类。您必须自己实现这样的类,或者找到提供此类功能的库。

答案 2 :(得分:0)

这是一个简单的通用不可变列表实现,包含Map&amp;过滤器支持:

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.

我在https://github.com/pierrejean-coudert/ReduxDelphi TodoMVC示例代码中使用它。