Spring4d: Spring.Collections.IEnumerator 和 System.IEnumerator

4

我有一个问题,本来应该很简单,但我找不到任何优雅的答案。

我有一个 IList<string> 实例,并且想要获取其所有不同(忽略大小写)值的逗号分隔字符串。

我以为可以使用 string.Join 辅助方法,因为它有一个很好的重载,接受一个 IEnumerator<string> 作为参数。不幸的是,我遇到了一个问题:spring4d 重新定义了 IEnumerator<T>,当然,在任何地方都使用自己的类型。

结果是以下代码无法编译:

var
  distinct: system.IEnumerator<string>;
begin
  result := inherited GetToken;
  if assigned(result) then
  begin
    if not Modules.Contains(STR_DID_SESSION_MODULE) then
      Modules.Add(STR_DID_SESSION_MODULE); 
    distinct := TDistinctIterator<string>.Create(Modules, TIStringComparer.Ordinal);
    result.CustomClaims.Items[STR_CLAIM_CUSTOM_MODULES] := string.Join(',', distinct);
  end;
end;

distinct的赋值失败,错误信息为E2010 不兼容类型:'System.IEnumerator<System.string>' 和 'Spring.Collections.Extensions.TDistinctIterator<System.string>'

或者,如果我从distinct中删除命名空间,则调用string.Join会失败。

你有任何想法应该怎么做吗?除了手动遍历迭代并手动执行连接之外?

1个回答

5

自己编写代码(顺便说一句,我更喜欢相反的参数顺序,但是为了保持 TStringHelper.Join 的签名,我将其保留在原样):

function StringJoin(const separator: string; const values: Spring.Collections.IEnumerable<string>): string; overload;
var
  e: Spring.Collections.IEnumerator<string>;
begin
  e := values.GetEnumerator;
  if not e.MoveNext then
    Exit('');
  Result := e.Current;
  while e.MoveNext do
    Result := Result + separator + e.Current;
end;

此外,您可以更简单地编写代码(无需手动从Spring.Collections.Extensions创建迭代器):

StringJoin(',', TEnumerable.Distinct<string>(Modules, TStringComparer.OrdinalIgnoreCase))

现在如果我们有接口帮助器,我们就可以轻松地为 IEnumerable<string> 编写一个帮助器,并添加 ToDelimitedString 或类似的内容。

谢谢,但我找不到StringJoin在哪里?它在一个单独的分支上吗? - Stephane
1
这个回答中有 - 这就是我写“自己写”(write it yourself)的原因 - 否则我本可以写“从...使用它”(use it from...)。(尽管我在最后一行的调用中忘记传递第一个参数/逗号) - Stefan Glienke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接