Мне нужно преобразовать разные списки интерфейсов в 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'
.
Есть ли способ сделать это с помощью универсального?
Возможность привести общий тип x<derived>
к x<base>
называется ковариацией (я писал об этом некоторое время назад — особенно в контексте коллекций — см. Обобщенные типы и дисперсия).
Вкратце: Delphi не поддерживает это, и вам придется использовать жесткое приведение, но будьте очень осторожны.
При выполнении любого доступа к чтению жесткого приведения TList<IOtherInterface>
к TList<IInterface>
это нормально, однако вы не должны добавлять к нему какой-либо интерфейс, кроме IOtherInterface
, что было бы возможно, потому что из-за жесткого приведения вы теперь имеете дело с TList<IInterface>
.
Если вы делаете это локально внутри одной процедуры, вам следует написать какой-нибудь комментарий, чтобы напомнить вам или кому-то еще об этом. Если вам не нужен доступ к индексу, вы также можете рассмотреть возможность его жесткого преобразования в TEnumerable<IInterface>
, потому что это разрешает только доступ для чтения и, следовательно, будет квалифицироваться как ковариантный в языках, поддерживающих дисперсию.