2014-03-27 52 views
2

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

问候!

回答

2

Delphi RTL不包含实现不可变或只读列表的类。你将不得不自己实现这样一个类,或者找到一个提供这种功能的库。

4

您可以使用Spring4D的IReadOnlyList<T>

如果你有一个IList<T>你只需要调用AsReadOnlyList并返回你相同的实例为IReadOnlyList<T>不提供方法来操作的列表(无AddDelete或setter的Items属性)。

然而,有从Java到unmodifiableList一个区别:

在Java中你真的得到了List<T>这将引发UnsupportedOperationException当您尝试修改它,而在Spring4D这是.NET为蓝本,你得到的东西,你不能调用任何修改操作。

0

下面是一个简单通用的不可变列表实现与地图&过滤器支持:

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示例代码。