Если у меня есть общий интерфейс с параметром ковариантного типа, например:
interface IGeneric<out T>
{
string GetName();
}
И если я определяю эту иерархию классов:
class Base {}
class Derived1 : Base{}
class Derived2 : Base{}
Затем я могу реализовать интерфейс дважды в одном классе, например, используя явную реализацию интерфейса:
class DoubleDown: IGeneric<Derived1>, IGeneric<Derived2>
{
string IGeneric<Derived1>.GetName()
{
return "Derived1";
}
string IGeneric<Derived2>.GetName()
{
return "Derived2";
}
}
Если я использую класс (non-generic) DoubleDown
и передаю его в IGeneric<Derived1>
или IGeneric<Derived2>
, он будет функционировать как ожидалось:
var x = new DoubleDown();
IGeneric<Derived1> id1 = x; //cast to IGeneric<Derived1>
Console.WriteLine(id1.GetName()); //Derived1
IGeneric<Derived2> id2 = x; //cast to IGeneric<Derived2>
Console.WriteLine(id2.GetName()); //Derived2
Однако при нажатии x
на IGeneric<Base>
получается следующий результат:
IGeneric<Base> b = x;
Console.WriteLine(b.GetName()); //Derived1
Я ожидал, что компилятор выдает ошибку, поскольку вызов является неоднозначным между двумя реализациями, но он возвратил первый объявленный интерфейс.
Почему это разрешено?
(вдохновленный класс, реализующий два разных IObservables?. Я пытался показать коллеге, что это провалится, но почему-то это не так)