Универсальный для преобразования списка интерфейсов в Delphi

Мне нужно преобразовать разные списки интерфейсов в TList<IInterface>.

TList<IOtherInterface> as TList<IInterface>

не работает, поэтому я попробовал этот общий вариант:

interface

type
    TInterfaceList = class(TList<IInterface>)
    end;

    TInterfaceListConverter<T:IEnumerable<IInterface>; I:IInterface> = class
        public
            function Convert(_from: T): TInterfaceList;
    end;

implementation

function TInterfaceListConverter<T, I>.Convert(_from: T): TInterfaceList;
begin
    Result := TInterfaceList.Create();
    for var i : I in _from do begin
        Result.Add(i as IInterface);
    end;
end;

но он не скомпилируется. Я понимаю E2010: Inkompatible types: 'I' and 'TObject'. Есть ли способ сделать это с помощью универсального?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Возможность привести общий тип x<derived> к x<base> называется ковариацией (я писал об этом некоторое время назад — особенно в контексте коллекций — см. Обобщенные типы и дисперсия).

Вкратце: Delphi не поддерживает это, и вам придется использовать жесткое приведение, но будьте очень осторожны.

При выполнении любого доступа к чтению жесткого приведения TList<IOtherInterface> к TList<IInterface> это нормально, однако вы не должны добавлять к нему какой-либо интерфейс, кроме IOtherInterface, что было бы возможно, потому что из-за жесткого приведения вы теперь имеете дело с TList<IInterface>.

Если вы делаете это локально внутри одной процедуры, вам следует написать какой-нибудь комментарий, чтобы напомнить вам или кому-то еще об этом. Если вам не нужен доступ к индексу, вы также можете рассмотреть возможность его жесткого преобразования в TEnumerable<IInterface>, потому что это разрешает только доступ для чтения и, следовательно, будет квалифицироваться как ковариантный в языках, поддерживающих дисперсию.

Другие вопросы по теме