Spring4d: Spring.Collections.IEnumerator и System.IEnumerator

У меня есть проблема, которая должна быть тривиальной, но на которую я не могу найти элегантного ответа.

У меня есть экземпляр 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 Incompatible types: 'System.IEnumerator<System.string>' and 'Spring.Collections.Extensions.TDistinctIterator<System.string>'

В качестве альтернативы, если я удалю пространство имен из отдельного, вызов string.Join завершится ошибкой.

Любая идея, как я должен это делать? За исключением ручного прохождения итерации и выполнения соединения вручную?


person Stephane    schedule 27.11.2017    source источник


Ответы (1)


Напишите это сами (FWIW я бы предпочел противоположный порядок параметров, но я оставил его таким с момента подписи 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 или что-то в этом роде.

person Stefan Glienke    schedule 27.11.2017
comment
Спасибо, но я нигде не могу найти StringJoin? Это в отдельной ветке? - person Stephane; 27.11.2017
comment
Это здесь, в этом ответе - поэтому я написал написать это самостоятельно - иначе я бы написал использовать его из ... (хотя забыл передать первый параметр/запятую при вызове в последней строке) - person Stefan Glienke; 27.11.2017