Ваш интерфейс IFoo кажется неправильным в этом использовании, он должен быть:
public interface IFoo<out T, **out** U>
С U
вне. Помните, что параметр общего типа out
означает, что он может изменяться «наружу». То есть вы можете неявно расширить тип до более широкого типа. In
, однако, означает, что вы можете неявно сузить тип «внутрь» к более конкретному типу. Это, конечно, грубые аналогии.
Таким образом, в случае присвоения hmm
вы неявно пытаетесь расширить параметр универсального типа интерфейса для U
с Derived
до Base
, но интерфейс объявляет его сужающимся (in
):
IFoo<IShape, Base> hmm = new MyFoo();
Так что он не может сделать неявное преобразование. Если вы действительно хотите неявно расширять этот интерфейс, аргумент второго типа должен быть out
вместо in
.
Обновление: после ваших комментариев я вижу, что большая дилемма состоит в том, что вы хотите, чтобы он был как входным, так и выходным, что на самом деле невозможно, так как это контравариантный ввод, вы не можете назначить интерфейс ковариантно IFoo<IShape, Base>
, к несчастью.
Вам нужно либо кодировать тот факт, что вы не можете присвоить IFoo<IShape,Base>
, либо создать Foo как:
public class MyFoo : IFoo<Rectangle, Base>
А затем приведите к Rectangle
внутри реализации. Главное, чтобы у одного и того же параметра типа не было и ковариации, и контравариантности.
Имеет ли это смысл?