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
相关产品推荐
相关产品推荐

