4

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

问候!

4

3 回答 3

7

您可以使用IReadOnlyList<T>Spring4D 中的。

如果您有一个IList<T>您只需调用AsReadOnlyList(自 2.0 起),它会返回与不提供操作列表的方法AsReadOnly相同的实例(no或属性的 setter )。IReadOnlyList<T>AddDeleteItems

但是,unmodifiableList与 Java 的不同之处在于:

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

于 2014-03-27T17:34:25.727 回答
3

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

于 2014-03-27T16:14:15.277 回答
1

这是一个简单的通用不可变列表实现,支持 Map & Filter :

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 示例代码中使用它。

于 2017-03-08T13:32:45.460 回答