Почему С# не разрешает наследование возвращаемого типа при реализации интерфейса

Есть ли какая-то рациональная причина, почему приведенный ниже код не является законным в С#?

class X: IA, IB
{
    public X test() // Compliation Error, saying that X is not IB
    {
        return this;
    }
}

interface IA 
{
    IB test();
}
interface IB { };

Ответ 1

Эта функция называется ковариацией возвращаемого типа. С# не поддерживает его по следующим причинам:

1) CLR не поддерживает его. Чтобы заставить его работать на С#, нам нужно просто наплевать целую кучу маленьких вспомогательных методов, которые будут отличать правильный тип возвращаемого значения. Там ничего не мешает вам сделать это самостоятельно.

2) Андерс считает, что ковариация возвращаемого типа не является хорошей языковой функцией.

3)\У нас много приоритетов для языка. У нас ограниченные бюджеты, поэтому мы стараемся делать только самые лучшие функции, которые могут быть доступны в любом выпуске. Конечно, это было бы неплохо, но достаточно легко сделать это самостоятельно, если захочешь. Лучше, чтобы мы тратили время на добавление функций, которые улучшают опыт разработчика или добавляют больше репрезентативной власти на язык.

Ответ 2

Вы можете использовать явную реализацию интерфейса, чтобы избежать проблемы.

class  X : IA, IB
{
  public X test()
  {
    return this;
  }

  IB IA.test()
  {
    return this;
  }
}

interface IA
{
  IB test();
}

interface IB
{
}

Ответ 3

Подписи должны точно соответствовать указаниям интерфейса. Нет причин, по которым вы не можете вернуть экземпляр X из метода, но подпись метода должна будет использовать IB.

Что касается разумной причины... это, вероятно, предпочтительнее с точки зрения удобочитаемости кода.

Вы можете реализовать интерфейс явно и предоставить альтернативную подпись, которая возвращает X, которая не определяется интерфейсом. Если вы знаете, что ваш IA на самом деле является X, вы можете использовать его вместо этого.

Ответ 4

Потому что С# не поддерживает co и contravriance для интерфейсов во время компиляции. Таким образом, реализация метода IA.Test() должна точно соответствовать его объявлению. Однако вы можете вернуть экземпляр X во время выполнения

Ответ 5

public X test();

Вы должны объявить тело для всех методов в любом классе, который не абстрактный.

Попробуйте следующее:

class X : IA, IB
{
    public IB test()
    {
        return new X();
    }
}

interface IA
{
    IB test();
}
interface IB { };