You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring4D中TDistinctIterator<string>.ToArray()触发访问错误如何解决?

问题原因

你的代码出现访问违例属于使用方式错误,并非框架bug,原因如下:

  • Spring4D的TDistinctIterator是内部实现类,设计上不推荐直接构造实例调用方法,你直接调用构造方法生成临时对象执行ToArray时,临时对象的生命周期管理逻辑会提前释放内部依赖的集合引用,导致访问非法内存。
  • 构造时传入的第二个nil参数为所有者参数,传nil时迭代器不会持有传入的d.Values集合的强引用,若集合生命周期提前结束也会触发访问错误。

正确实现方案

方案1:使用Spring4D内置扩展方法(推荐)

直接引用Spring.Collections.Extensions单元,调用框架封装好的Distinct扩展方法,无需手动处理迭代器生命周期:

uses
  Spring, Spring.Collections, Spring.Collections.Extensions;

var
  d: IDictionary<Integer, String>;
  v: Vector<String>;
begin
  d := TDictionary<Integer, String>.Create();
  d.Add(1, 'test');
  d.Add(2, 'test');
  d.Add(3, 'test');

  v := d.Values.Distinct.ToArray;
end;

注意这里使用IDictionary接口替代直接使用TDictionary类,Spring4D集合接口会自动管理生命周期,避免手动释放的问题。

方案2:手动使用TDistinctIterator(原有写法修正)

如果需要手动构造迭代器,要通过IEnumerable<T>接口持有迭代器实例,保证生命周期正常:

uses
  Spring, Spring.Collections, Spring.Collections.Iterators;

var
  d: IDictionary<Integer, String>;
  distinctIter: IEnumerable<string>;
  v: Vector<String>;
begin
  d := TDictionary<Integer, String>.Create();
  d.Add(1, 'test');
  d.Add(2, 'test');
  d.Add(3, 'test');

  distinctIter := TDistinctIterator<string>.Create(d.Values, nil);
  v := distinctIter.ToArray;
end;

方案3:不依赖Spring4D迭代器的原生去重方案

可以直接用TSet实现自动去重,不需要依赖Spring4D的迭代器逻辑:

uses
  System.Generics.Collections;

var
  d: TDictionary<Integer, String>;
  distinctSet: TSet<string>;
  v: TArray<string>;
begin
  d := TDictionary<Integer, String>.Create();
  try
    d.Add(1, 'test');
    d.Add(2, 'test');
    d.Add(3, 'test');

    distinctSet := TSet<string>.Create();
    try
      distinctSet.Union(d.Values);
      v := distinctSet.ToArray;
    finally
      distinctSet.Free;
    end;
  finally
    d.Free;
  end;
end;

内容的提问来源于stack exchange,提问作者Laurens

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 14:54:05